Typhoon:如何修补与组件键相关的定义?

时间:2013-11-29 17:20:25

标签: typhoon

我正在尝试实施修补程序,如文档和此SO帖子所示:Typhoon: How to get an instance conforming to a protocol for production, and another for tests?

我正在使用块程序集并得到错误:

[WPAnalyticsClientImplementation key]: unrecognized selector sent to instance 0x9eb01d0

TyphoonPatcher.m: 46

我的类实现没有响应这个选择器。应该是?密钥如何与修补过程相关?

context(@"when the controller does something", ^{

        it(@"should work", ^{
            // This is an application test, so the factory has already been set in the app delegate.
            TyphoonComponentFactory *factory = [TyphoonComponentFactory defaultFactory];

            TyphoonPatcher* patcher = [[TyphoonPatcher alloc] init];
            [patcher patchDefinition:[factory componentForType:@protocol(WPAnalyticsClient)] withObject:^id
             {
                 id mockAnalytics = [KWMock mockForProtocol:@protocol(WPAnalyticsClient)];
                 [[mockAnalytics should] conformToProtocol:@protocol(WPAnalyticsClient)];
                 [mockAnalytics stub:@selector(getSomeString) andReturn:theValue(@"fake implementation")];

                 return mockAnalytics;
             }];

            [factory attachPostProcessor:patcher];

            // The default factory should now return the mocked client.
            id <WPAnalyticsClient> client = [factory componentForType:@protocol(WPAnalyticsClient)];

            NSLog(@"conforms: %i", [client conformsToProtocol:@protocol(WPAnalyticsClient)]);
            NSString *actualValue = [client getSomeString];
            NSLog(@"someString: %@", actualValue);
            [[theValue([actualValue isEqualToString:@"fake implementation"]) should] equal:theValue(YES)];
        });
    });

AppDelegate.m

TyphoonComponentFactory *factory = ([[TyphoonBlockComponentFactory alloc] initWithAssembly:[WPAssembly assembly]]);
[factory makeDefault];

1 个答案:

答案 0 :(得分:3)

上面显示的修补代码不是很正确,而不是修补 实例 ,修补 定义

修补程序的工作方式是使用TyphoonComponentFactoryPostProcessor来改变定义。

所以不要这样做:

[patcher patchDefinition:[factory componentForType:@protocol(WPAnalyticsClient)] 
    withObject:^id. . .

你应该这样做:

MyAssemblyType* assembly = [MyAssemblyType assembly];
TyphoonComponentFactory* factory = [TyphoonBlockComponentFactory factoryWithAssembly:assembly];   
[patcher patchDefinition:[assembly myComponentToPatch] withObject . . . ]; 

修补默认程序集::

因为您正在修补默认程序集,而不是创建新程序集,所以必须按如下方式传递定义:

[patcher patchDefinition:[[MyAssemblyType assembly] myAnalticsService] withObject. . . ]

组件密钥与装配接口

假设你有一个组件如下:

- (id) myAnalyticsService 
{
    return [TyphoonDefinitionWithClass. . . . etc]; 
}

。 。 。然后你的组件的关键是 @“myAnalyticsService”,所以你也可以使用:

[patcher patchDefinitionWithKey:@"myAnalyticsService" . . ];

构建时与运行时的程序集接口

这是一个可能引起一些混淆的概念:

装配界面有两个用途。在构建时它返回TyphoonDefinition,而在运行时它返回定义中定义的实际类型。所以。 。

  • 在构建时,我们可以定义组件。

  • 在运行时,我们可以使用汇编界面上的方法名解析组件

示例:

MyAssemblyType* assembly = (MyAssemblyType*) [TyphoonComponentFactory defaultFactory];
//Use the assembly interface instead of a 'magic string'
AnalyticsService* service = [assembly analyticsService]; 

这是很多信息。 。 。如果有些事情仍然不清楚,请告诉我。