Closed raymondkam closed 1 week ago
Checkout the documentation for once.
https://hmlongco.github.io/Factory/documentation/factory/modifiers/#Once
Yes, you changed the context... but when UserManager is initialized it's going to resolve authService, which calls the authService factory, which calls the onText modifier again before it resolves.
Yep, you set it. And then the factory you specified sets it back.
As I said in the docs it’s probably best simply to be careful in regard to what goes into our basic Factory definition.
Contexts, in particular, should probably be defined in the Container’s autoRegister function.
Thanks for the quick reply @hmlongco
The Container autoRegister
works for the use case I'm thinking of, where I can auto register a default mock class for unit tests and where I need to do an override I can specify within the unit test class itself
extension Container: AutoRegistering {
public func autoRegister() {
#if DEBUG
authService
.context(.test) {
MockAuthService() // This gets called in the test context if there's no override specified
}
#endif
}
}
Then back in my unit test class
final class UserManagerTests: XCTestCase {
var mockAuthService: MockAuthService!
var sut: UserManager!
func setUp() {
let mockAuthService = MockAuthService()
self.mockAuthService = mockAuthService
Container.shared.authService.onTest {
mockAuthService // Override is now called
}
sut = UserManager()
}
...
}
Using once
should also work for that same scenario. Appreciate the help pointing me to the right place 👍
Just reread that and realized I probably should have quoted once.... ;)
Checkout the documentation for once.
When using Contexts with either a list of contexts
.context(.test, .preview)
or using one of the existing helpers (onTest
,onPreview
, etc), it seems like there's no way to override or replace the factory that is specified for the contextThe reason for overriding the factory is in unit tests when I want to specify an exact instance of a dependency that I want to be able to control (such as manipulating the state of a mock), but also have the context factory for other unit tests where I don't need to directly control that dependency.
Here's a small example of the scenario
Let's say I have a protocol
AuthServicing
where I want to register a mock when running unit tests (and for previews)Then let's say I have a class that has this
AuthServicing
dependencyThen inside a unit test for the
UserManager
, I want to have a specific instance of my mock which has functions to control the mock object for various scenariosI've tried a couple of things such as using
.reset
on the type or on the container but it always reverts back to the original factory registration in the Container extension. The only way I've gotten this to work is to avoid using contexts where the factory override in the unit test class will work. The other alternative was to add a cached/singleton scope where I can resolve the mock instance and configure it there, but I thought the override would be cleaner and also allow forpush
andpop
Container features to work as well.Thanks in advance, let me know if I can provide any additional details