refactor(core): replace .boundaries() with .collaborate() and .exclude()
Summary
Replaces the .boundaries() API with semantically clearer .collaborate() and .exclude() methods. This refactoring improves API clarity and provides identity-based mocking that is stable across refactoring.
Breaking Changes
- Removed:
.boundaries()method - Replaced with:
.collaborate()(no params) +.exclude([...])(min 1 class required) - Internal: Mode type changed from
'boundaries'to'collaborate' - Internal:
boundaryClassesrenamed toexcludedClasses
New API
// Before (boundaries)
TestBed.sociable(UserService)
.boundaries([ExpensiveService])
.compile()
// After (collaborate)
TestBed.sociable(UserService)
.collaborate()
.exclude([ExpensiveService])
.compile()
// Simple case (no exclusions)
TestBed.sociable(UserService)
.collaborate()
.compile()
Benefits
✅ Clear semantics: .collaborate() communicates intent better than .boundaries()
✅ Identity-based mocking: Exclusions based on class identity, not graph position (refactor-stable)
✅ Type safety: TypeScript enforces minimum 1 item in exclude array via tuple type [Type, ...Type[]]
✅ Natural boundaries preserved: Token injections still auto-mocked
✅ .mock() still works: Can customize excluded classes or mock additional ones
Technical Details
Why This Change?
The term "boundaries" was semantically confusing:
- Sounded like: Creating barriers/isolation at edges
- Actually did: Blacklist specific classes to mock, everything else real
- Problem: Didn't clearly communicate "most dependencies collaborate naturally"
The new API aligns with Martin Fowler's "Sociable Tests" concept where dependencies work together by default, with selective exclusions for expensive/external concerns.
Identity-Based vs Position-Based Mocking
Identity-based (new API):
.exclude([StripeClient]) // "Mock StripeClient wherever it appears"
✅ Stable across refactoring - if StripeClient moves deeper in the graph, it stays mocked
Position-based (hypothetical "mock leaves"):
.mockLeaves() // "Mock whatever is at graph edges"
❌ Fragile - refactoring changes which classes are leaves, breaking tests
Files Changed
packages/core/src/services/builders/sociable-unit-builder.ts- Core APIpackages/core/src/errors/dependency-not-configured.error.ts- Error typespackages/core/src/services/dependency-resolver.ts- Resolution logicpackages/core/src/services/unit-mocker.ts- Options types- Test files renamed and updated (all 105 tests passing)
Test Coverage
Test Suites: 8 passed, 8 total
Tests: 105 passed, 105 total
Coverage: 95.27% statements, 82.92% branches
Migration Guide
Users on v4 beta should update:
// Old
.boundaries([ClassA, ClassB])
// New
.collaborate()
.exclude([ClassA, ClassB])
Since this is a beta release, breaking changes are acceptable for semantic improvements.
Codecov Report
:x: Patch coverage is 93.33333% with 1 line in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 93.73%. Comparing base (7427aff) to head (2a31176).
:warning: Report is 1 commits behind head on next.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| ...ore/src/services/builders/sociable-unit-builder.ts | 92.30% | 0 Missing and 1 partial :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## next #912 +/- ##
==========================================
+ Coverage 93.07% 93.73% +0.65%
==========================================
Files 26 26
Lines 650 654 +4
Branches 109 109
==========================================
+ Hits 605 613 +8
+ Misses 37 33 -4
Partials 8 8
| Flag | Coverage Δ | |
|---|---|---|
| core.unit | 94.03% <93.33%> (+1.42%) |
:arrow_up: |
| di.inversify | 100.00% <ø> (ø) |
|
| di.nestjs | 87.25% <ø> (ø) |
|
| doubles.jest | 100.00% <ø> (ø) |
|
| doubles.sinon | 100.00% <ø> (ø) |
|
| doubles.vitest | 100.00% <ø> (ø) |
|
| unit | 77.27% <ø> (ø) |
Flags with carried forward coverage won't be shown. Click here to find out more.
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.