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?

Eugen Martynov
  • 19,888
  • 10
  • 61
  • 114

1 Answers1

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.

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
  • But how my view controller will access configured factory or I should also move controller instantiation to factory? – Eugen Martynov Feb 20 '14 at 12:23
  • 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: http://bit.ly/1nQce7k, and look-up the next object graph. Or use: http://bit.ly/1a93dFE or: http://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. – Jasper Blues Feb 20 '14 at 13:15
  • Have you tried the sample app? https://github.com/typhoon-framework/Typhoon-example – Jasper Blues Feb 20 '14 at 13:17
  • 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. – Eugen Martynov Feb 20 '14 at 13:41
  • Injecting factory is also possible solution – Eugen Martynov Feb 20 '14 at 13:43
  • 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. – Jasper Blues Feb 20 '14 at 13:48
  • 1
    Update: We have removed the restriction on setting the default factory more than once. – Jasper Blues Apr 13 '14 at 04:44
  • thank you for the update, so I could now play with default factory in my tests :) – Eugen Martynov Apr 13 '14 at 05:19
  • @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', :head – Jasper Blues Apr 13 '14 at 07:38