我正在尝试实施修补程序,如文档和此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];
答案 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];
这是很多信息。 。 。如果有些事情仍然不清楚,请告诉我。