Skip to content

Allow tests to initialize non-stubbed dependencies #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

patrickroteman
Copy link
Contributor

Add flag allow-tests-to-init-real-dependencies that will force all dependency resolver methods to be declared as internal rather than private or fileprivate so that any @Testable import of the generated code is able to initialize both the dependency container and access all of the DependencyResolvers. Note that this does NOT change any of the test mock generation, this is altering the access level of the real dependencies to be able to facilitate customization of test dependencies. It is then possible to mix and match real and mocked dependencies based on your test setup. Previously this was not possible because the MainDependencyContainer initializer was private, along with all of the dependency resolvers. Without setting this flag, there is no impact to code generation so this change is fully backward compatible.

For example, now inside of unit tests for some CoolSampleApp , you would be able to do this:

@Testable import CoolSampleApp
class ExampleTests: XCTestCase {
  func testExample() {
    let realDependencyContainer = MainDependencyContainer()
    let realDependency = realDependencyContainer.specificDependencyResolver().specificDependency
    // Test code that actually uses the real dependency
  }
}

It is still possible to use the tests flag to generate stubbed dependencies and use those alongside each other. For example, you can now mix and match real and mocked dependencies for a class under test to be able to do integration or feature level tests. Continuing the textExample() from above, you may see something like this:

  func testExample() {
    let realDependencyContainer = MainDependencyContainer()
    let realDependencyFoo = realDependencyContainer.dependencyFooResolver().dependencyFoo

    let mockedDependencyContainer = StubbedDependencies()
    let mockedDependencyBar = StubbedDependencies.dependencyBarDouble

    let objectUnderTest = SomeClass(foo: realDependencyFoo, bar: mockedDependencyBar)
    // Actual test logic and validation
  }

Also update dependencies and tools versions in the package so that it can compile with modern tool chains (Xcode 16.x, Swift 5).

Add flag `allow-tests-to-init-real-dependencies` that will force all dependency resolver methods to be declared as `internal` rather than `private` or `fileprivate` so that any `@Testable import` of the generated code is able to initialize both the dependency container and access all of the DependencyResolvers. Note that this does **NOT** change any of the test mock generation, this is altering the access level of the **real** dependencies to be able to facilitate customization of test dependencies. It is then possible to mix and match real and mocked dependencies based on your test setup. Previously this was not possible because the MainDependencyContainer initializer was private, along with all of the dependency resolvers. Without setting this flag, there is no impact to code generation so this change is fully backward compatible.

For example, now inside of unit tests for some `CoolSampleApp` , you would be able to do this:
```
@testable import CoolSampleApp
class ExampleTests: XCTestCase {
  func testExample() {
    let realDependencyContainer = MainDependencyContainer()
    let realDependency = realDependencyContainer.specificDependencyResolver().specificDependency
    // Test code that actually uses the real dependency
  }
}
```

It is still possible to use the `tests` flag to generate stubbed dependencies and use those alongside each other. For example, you can now mix and match real and mocked dependencies for a class under test to be able to do integration or feature level tests. Continuing the `textExample()` from above, you may see something like this:

```
  func testExample() {
    let realDependencyContainer = MainDependencyContainer()
    let realDependencyFoo = realDependencyContainer.dependencyFooResolver().dependencyFoo

    let mockedDependencyContainer = StubbedDependencies()
    let mockedDependencyBar = StubbedDependencies.dependencyBarDouble

    let objectUnderTest = SomeClass(foo: realDependencyFoo, bar: mockedDependencyBar)
    // Actual test logic and validation
  }
```
@patrickroteman patrickroteman merged commit 9b11e36 into scribd:master Apr 18, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants