Injecting mock with Typhoon
Asked Answered
S

1

2

I'm trying to write XCTest and inject mocked dependency with Typhoon.

Here is code in my ViewController:

   - (instancetype)init {
    self = [super init];

    MDMainAssembly *assembly = (MDMainAssembly *) [TyphoonComponentFactory defaultFactory];
    self.alertManager = [assembly alertManager];

    return self;
   }

Here is how I'm trying to change injection:

    self.mockedAlertManager = mock([MDAlertManager class]);

    MDMainAssembly *assembly = [MDMainAssembly assembly];
    TyphoonComponentFactory *factory = [TyphoonBlockComponentFactory factoryWithAssembly:assembly];
    TyphoonPatcher *patcher = [[TyphoonPatcher alloc] init];
    [patcher patchDefinition:[assembly alertManager] withObject:^id {
        return self.mockedAlertManager;
    }];

    [factory attachPostProcessor:patcher];

However tests are failing because this factory not possible to set as default. I configure in AppDelegate factory:

    TyphoonComponentFactory *factory = [[TyphoonBlockComponentFactory alloc] initWithAssemblies:@[
        [MDMainAssembly assembly],
    ]];
    [factory makeDefault];

How to get out of this situation?

Shetler answered 20/2, 2014 at 11:30 Comment(0)
A
2

We created the defaultFactory feature for a limited number of cases. The main is:

  • Getting access to Typhoon and looking up a dependency for a class that isn't being managed by Typhoon. Generally this isn't required.

Although you could use it in tests, we recommend instead creating and destroying a Typhoon container for each test run. To avoid duplication, you could create a method as follows:

@implementation IntegrationTestUtils

+ (TyphoonComponentFactory*)testAssembly
{
    TyphoonComponentFactory* factory = [[TyphoonBlockComponentFactory alloc] initWithAssemblies:@[
        [MyAppAssembly assembly],
        [MyAppKernel assembly],
        [MyAppNetworkComponents assembly],
        [MyAppPersistenceComponents assembly]
    ]];

    id <TyphoonResource> configurationProperties = [TyphoonBundleResource withName:@"Configuration.properties"];
    [factory attachPostProcessor:[TyphoonPropertyPlaceholderConfigurer configurerWithResource:configurationProperties]];

    return factory;
}

. . if required you could attach a patcher to this assembly.

Attaching a patcher to the default factory:

If you were to apply a patcher to the default assembly, you'd most probably want to un-patch again. This feature is in the backlog here.

Adventitia answered 20/2, 2014 at 12:18 Comment(9)
But how my view controller will access configured factory or I should also move controller instantiation to factory?Shetler
Yes, we recommend to build your view controllers with Typhoon. Then, Inject the dependencies for the current use-case. But for the next use-case, inject the assembly: bit.ly/1nQce7k, and look-up the next object graph. Or use: bit.ly/1a93dFE or: bit.ly/1mdnpZ1 . . If this is not suitable for you and you want to stick with defaultAssembly, perhaps an easier way to mock is to provide a setter so you can inject a mock factory. . It depends if you want an configured integration test or pure unit test.Adventitia
Have you tried the sample app? github.com/typhoon-framework/Typhoon-exampleAdventitia
I looked to some sources when I faced with described issue. I'm using my experience with Dagger and Guice. Because with android you don't have access for Activities instantiation you always injects object on later stages with preconfigured container.Shetler
Injecting factory is also possible solutionShetler
Let us know how you go with the recommended approaches - if they work ok for you. Summary again: Inject dependencies for current use case on view controller. . for transition to next view controller, inject the factory (posing as the assembly interface) so you can retrieve the next VC. 3 ways to do this referenced in comments above.Adventitia
Update: We have removed the restriction on setting the default factory more than once.Adventitia
thank you for the update, so I could now play with default factory in my tests :)Shetler
@EugenMartynov Yes, this is currently on master (Typhoon 2.0-style). . we'll be releasing 2.0 in ~ 2 weeks. To use: pod update 'Typhoon', :headAdventitia

© 2022 - 2024 — McMap. All rights reserved.