objective-ctyphoonkifintegration-testing

How to reset patched components by TyphoonPatcher


I have problem with TyphoonPatcher used in Integration Tests. I'm using KIF for integration tests. Sometimes i need to stub http client or class responsible for saving data in database. The easiest way is use TyphoonPatcher.

Lets say that i need patch patch knight to stubbed knight for TestCase A, for all test cases, so i'm doing this in beforeAll callback

code responsible for patching component:

MiddleAgesAssembly* assembly = [[MiddleAgesAssembly assembly] activate];

TyphoonPatcher* patcher = [[TyphoonPatcher alloc] init];
[patcher patchDefinitionWithSelector:@selector(knight) withObject:^id{
Knight* mockKnight = mock([Knight class]);
[given([mockKnight favoriteDamsels]) willReturn:@[
    @"Mary",
    @"Janezzz"
]];

return mockKnight;

}];

[assembly attachPostProcessor:patcher];

Knight* knight = [(MiddleAgesAssembly*) factory knight]

And now in TestCase B i want to have clear state of app, without any patched componenets.

Problem? Knight in class B is still replaced with other mocked or stubbed class.

Is there any way to revert patch from TestCase A?


Solution

  • TyphoonPatcher is a kind of TyphoonAbstractDetachableComponentFactoryPostProcessor so you can simply call the detach method of the patcher. Note that this only works if the patcher is the last post processor to be attached. Typhoon doesn't know how to unwind state to an arbitrary depth.

    **Example: **

    - (void)test_allows_detaching_patcher
    {
        [self applyAPatch];
        [self assertPatchApplied];
    
        XCTAssertFalse([_assembly componentForKey:@"knight"] == [_assembly componentForKey:@"knight"]);
        XCTAssertTrue([_assembly componentForKey:@"cavalryMan"] == [_assembly componentForKey:@"cavalryMan"]);
    
        [_patcher detach];
    
        Knight *knight = [_assembly componentForKey:@"knight"];
        LogDebug(@"%@", [knight favoriteDamsels]);
    }
    

    Generally use a separate Typhoon for tests:

    Also note that, in general we recommend that you use a separate instance of Typhoon for tests. When doing this it should be unnecessary to detach a patcher. However if it suits you better for a specific case, then detach is the way to go.