3

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?

user3292998
  • 209
  • 1
  • 8

2 Answers2

1

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.

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
0

Typically componenets are patched for one test case, if you want to get rid of patched components, and have clear state for next KIFTestCase tests you can just put:

exit(0)

in afterAll, like:

- (void)afterAll {
    [super afterAll];
    exit(0);
}

Be aware, that this works only between running TestCase, i you want to rollback patched component for some test methods in TestCase, you should use solution mentioned above.

user3292998
  • 209
  • 1
  • 8