1

我想在我的视图控制器中注入一个视图,以便我可以在我的单元测试中注入一个模拟视图(WPDependencyInjectorImplementation是我的TyphoonAssembly子类)。

我理想loadView的方法如下所示:

- (void)loadView {
    WPDependencyInjectorImplementation *injectorAssembly = (WPDependencyInjectorImplementation *) [TyphoonAssembly defaultAssembly];
    self.view = [injectorAssembly someView];
}

鉴于从 xib 创建视图的代码如下:

NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"WPSomeView" owner:nil options:nil];
return [views firstObject];
4

1 回答 1

1

That's right you just override loadView, rather than looking up the view from the container, as you've shown, you should provide the view via an initializer or property setter. And then in loadView, set it to the injected view as follows:

- (void)loadView 
{
    [self.view = _myInjectedView]; //Do this rather than looking it up via the TyphoonFactory - easier to test. 
}

If you do it this way:

  • You can refer to the view via it's actual type, rather than down-casting from UIView
  • It'll be really simple to mock-out in a pure unit test. (No need for TyphoonPatcher, swizzling, etc).

Here's an example:

- (id)userDetailsController
{
    return [TyphoonDefinition withClass:[UserDetailsController class] initialization:^(TyphoonInitializer* initializer)
    {
        initializer.selector = @selector(initWithSession:userDetailsView:);
        [initializer injectWithDefinition:[self session]];
        [initializer injectWithDefinition:[self userDetailsView]];
    }];
}

- (id)userDetailsView
{
    return [TyphoonDefinition withClass:[UserDetailsView class] 
        properties:^(TyphoonDefinition* definition)
    {
        //circular dependency. Can also be set within VC. 
        [definition injectProperty:@selector(delegate) 
            withDefinition:[self userDetailsController]]; 
        [definition injectProperty:@selector(sideMargin) 
            withValueAsText:@"${view.field.default.side.margin}"];
    }];
}

Injecting From a Xib

We don't actually have a Xib factory we can provide you yet. It should be a quick job to define one using a similar pattern to the object that emits a theme here, so you'll have a component in the DI container for each of your Xib-based views, and just inject that directly.

Alternatively you could use our new TyphoonFactoryProvider.

If you get stuck, please let us know and one of us will find some time to create and push that Xib-view-factory for you.

于 2013-12-10T12:27:34.643 回答