Skip to main content

Testable App Architecture

The Menditect Testability Framework is relies on two architectural principles: Separation of Concerns (SoC) and Dependency Injection (DI). These principles are not abstract design preferences - they directly determine how easily and reliably an Mendix application can be tested.

This page explains why SoC and DI matter for testability.
The how is explained in the sub-page Guiding Principles for SoC and DI.

1. Separation of Concerns in Mendix

Separation of Concerns means structuring an application so that each part has one clear responsibility. Menditects Testability Framework applies three mechanisms that support Separation of Concern:

1.1. Layering (Horizontal Separation)

Logic is grouped into distinct layers, each with a clear role, naturally aligning with the testing pyramid.:

  • Touchpoint Layer – entry points triggered by users or external systems
  • Application Logic Layer – orchestration and process coordination
  • Domain Logic Layer – core business rules, validations, and state management

For details read the page App Layers.

1.2 Componentization (Vertical Separation)

The application is divided into functional components, usually represented as Mendix modules or specific folder structures. Each component encapsulates its domain model, business rules and microflows.

This creates modular building blocks that can be tested in isolation.

For details read the page App Components.

1.3 Encapsulation Through Private Microflows

Each component exposes only a well-defined public microflows with which other components may interact. Internal implementation details remain hidden behind private microflows.

Encapsulation reduces coupling and prevents tests from depending on internal logic.

For details read the page Private & Public Microflows.

2. Why SoC Improves Testability

When responsibilities are clearly separated, each part of the application becomes:

  • Smaller and more focused → easier to understand and to test
  • Predictable in behavior → easier to write assertions for
  • Isolated from unrelated changes → tests don’t break when other features evolve
  • Stable over time → a strong foundation for automation

3. What DI Means in Mendix

Dependency Injection (DI) is a design principle where a function receives the information and logic it needs instead of retrieving or implementing it itself. In classical software development, this often means injecting other objects or services.

In Mendix, DI applies specifically to data and configuration because microflows cannot be injected in other microflows. DI in Mendix consists of two key ideas:

3.1 Data Injection

Instead of retrieving objects inside a microflow:

  1. Separate data retrieval from logic: Move all 'retrieve microflow actions' into specialized getter microflows (GET), making them solely responsible for data fetching.
  2. Pass objects as input parameters to the microflow that performs the core logic.

This makes dependencies explicit and avoids hidden data access.

3.2 Configuration Injection

Configuration values (constants, settings objects, parameters) should be:

  • retrieved once at the start of a process, and
  • passed as input parameters into the relevant microflows .

This prevents microflows from relying on hidden or global state.

3. Why DI Improves Testability

Dependency Injection makes dependencies explicit and controllable, which is essential for reliable automated tests. Injected dependencies let tests use controlled, predefined versions of external components. Because nothing unpredictable is fetched or created during the test, results stay consistent every run, making the test environment deterministic.

DI enables the following:

2.1 Isolated Testing

When a microflow receives every required object as a parameter, it can be tested:

  • without database dependencies
  • without complex setup
  • without retrieving global configuration

This is the foundation of true unit testing in Mendix.

2.2 Easy Mocking

Injecting objects instead of retrieving them internally allows test automation tools to:

  • supply mock objects
  • simulate edge cases
  • override configuration
  • test error paths and boundary conditions

2.3 Stable and Predictable Tests

Tests no longer depend on:

  • dynamic database state
  • unpredictable associations
  • runtime configuration changes