Modular monolith boundaries
Try to bypass a module's business rule
Test the paths most likely to avoid the public contract: direct repository imports, background jobs and administrative updates. The same invariant should hold for each supported caller.
In this article
Choose one rule with a clear result
Use a synthetic dispatched order whose delivery address must no longer change. Verify the public order operation rejects the request and leaves the record unchanged.
This establishes the intended rule, but it does not prove that other parts of the application use it. The next tests should target access paths that can mutate the same state.
Keep the fixture isolated from real fulfilment and notifications so the test can inspect all writes without external consequences.
Attempt an internal import
From another module, try importing the order repository or internal entity mutator. The project's visibility or dependency check should reject that access if it is meant to be private.
If the language cannot enforce the boundary directly, add an appropriate architecture or lint rule and run it in the normal check pipeline. A rule documented only in a diagram will not stop an accidental import during a rushed fix.
Test the actual exported package paths. A top-level public entry point is not sufficient if wildcard exports still expose every internal file.
Exercise non-interactive callers
Run the same address change through a scheduled job, import process and supported administrative action. Confirm each route reaches the eligibility rule or an explicitly authorised exception with its own checks.
Inspect direct SQL or shared data-access helpers used by those paths. A background worker can bypass module ownership even when every web controller is well structured.
Add a race in which dispatch begins while the address change is being prepared. The final write should follow the chosen concurrency rule rather than relying on an earlier read that has become stale.
Inspect the record and side effects
Assert that the forbidden address change did not commit and that no notification or downstream event claims it did. A rejected response can still hide an unintended side effect if validation occurs too late.
For a deliberate administrative exception, verify the actor, reason and resulting event are recorded. Exceptions should be testable contracts, not undocumented repository access.
Keep the bypass cases as regression tests. When a new integration or batch process is added, use them to confirm that the module still owns the rule across every supported route to its data.
Primary sources
Microsoft Learn: common web application architecturesPostgreSQL: privilegesReferences checked 11 September 2026.