2

我正在尝试实现一个补丁程序,如文档和这篇 SO 帖子中所示:Typhoon: How to get an instance conforming to a protocol for production, and another for testing? .

我正在使用块组装并得到错误:

[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];
4

1 回答 1

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]; 

这是很多信息。. . 如果还有什么不清楚的,请告诉我。

于 2013-12-02T00:08:55.630 回答