Ios 验证是否使用两个不同的参数调用了两次方法

Ios 验证是否使用两个不同的参数调用了两次方法,ios,objective-c,core-data,ocmock,Ios,Objective C,Core Data,Ocmock,我想测试一个方法是否被调用两次,第一次传递参数的YES,第二次NO。 复杂的是,我想测试的方法是类方法,我不确定这是否与我看到的问题有关 我的测试如下所示: - (void)testCreatesMessagesWithCorrectHTMLForcing { id messageClassMock = OCMClassMock([MyMessage class]); [messageClassMock setExpectationOrderMatters:YES]; [

我想测试一个方法是否被调用两次,第一次传递参数的
YES
,第二次
NO
。 复杂的是,我想测试的方法是类方法,我不确定这是否与我看到的问题有关

我的测试如下所示:

- (void)testCreatesMessagesWithCorrectHTMLForcing {
    id messageClassMock = OCMClassMock([MyMessage class]);
    [messageClassMock setExpectationOrderMatters:YES];
    [[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
                                                          forceHTMLRendering:YES
                                                                   inContext:[OCMArg any]];
    [[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
                                                          forceHTMLRendering:NO
                                                                   inContext:[OCMArg any]];
    NSMutableDictionary *mockJSON = [self.mockJSON mutableCopy];
    MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
                                                                       inContext:self.mockContext];
    OCMVerifyAll(messageClassMock);
    [messageClassMock stopMocking];
}
threadForDictionary:inContext:
方法为线程中的每条消息调用
messageForDictionary:forceHTMLRendering:inContext:
,并需要一个对象作为返回值。这就是为什么我添加了
和forwardToRealObject
,否则我会得到异常,因为返回值是
nil
。正如您可以从签名中想象的那样,它是关于将JSON解析为CoreData对象的

添加此测试会使同一测试文件中的所有其他测试失败,并显示以下消息

unexpected method invoked: messageForDictionary:<OCMAnyConstraint: 0x7fab637063d0> forceHTMLRendering:NO inContext:<OCMAnyConstraint: 0x7fab63706eb0>
expected:   messageForDictionary:<OCMAnyConstraint: 0x7fab6371cb20> forceHTMLRendering:YES inContext:<OCMAnyConstraint: 0x7fab6371fb50>"
但是,
checkWithBlock:
似乎没有被调用。(测试在
expect(firstInvocation).to.equal(NO);
处失败)

这是怎么回事


有没有另一种(更好的?)方法可以用OCMock编写测试,检查方法是否以正确的顺序使用正确的参数调用?

我终于找到了第一个解决方案。问题是,如果
expectationOrderMatters
YES
,OCMock就会抛出异常。由于异常,测试提前退出,并且从未调用
stopMocking
,这导致模拟未正确清理。随后对模拟方法的调用失败,导致所有测试失败

解决方案是确保调用StopMock,即使一切都出错。我是通过像这样使用
try catch
来实现这一点的(对宏的更改以及使用
andReturn
而不是
和forwardtorealObject
都无关紧要):


注意catch块中的
XCTFail
:您需要包括它,否则您的测试将是绿色的,尽管发生了异常。

似乎也有帮助的是省略了
[messageClassMock setExpectationOrderMatters:YES]。但是,这样做意味着无论调用方法的顺序如何,只要使用
YES
调用一次,使用
no
调用一次,我的测试都会通过。
- (void)testCreatesMessagesWithCorrectHTMLForcing {
    id messageClassMock = OCMClassMock([MyMessage class]);
    __block BOOL firstInvocation = YES;
    [[[messageClassMock expect] andForwardToRealObject] messageForDictionary:[OCMArg any]
                                                          forceHTMLRendering:[OCMArg checkWithBlock:^BOOL (id obj) {
        NSNumber *boolNumber = obj;
        expect([boolNumber boolValue]).to.equal(firstInvocation);
        firstInvocation = NO;
        return YES;
    }]
                                                                   inContext:[OCMArg any]];
    NSMutableDictionary *mockJSON = [self.mockJSON mutableCopy];
    MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
                                                                       inContext:self.mockContext];
    expect(firstInvocation).to.equal(NO);
    OCMVerifyAll(messageClassMock);
    [messageClassMock stopMocking];
}
MyMessage *message = [MyMessage insertInManagedObjectContext:self.mockContext];
id messageClassMock = OCMStrictClassMock([MyMessage class]);
@try {
    [messageClassMock setExpectationOrderMatters:YES];
    OCMExpect([messageClassMock messageForDictionary:[OCMArg any]
                                  forceHTMLRendering:NO
                                           inContext:[OCMArg any]]).andReturn(message);
    OCMExpect([messageClassMock messageForDictionary:[OCMArg any]
                                  forceHTMLRendering:YES
                                           inContext:[OCMArg any]]).andReturn(message);
    MyThread *classUnderTest = [MyThread threadForDictionary:self.mockJSON
                                                                       inContext:self.mockContext];
    OCMVerifyAll(messageClassMock);
}
@catch (NSException *exception) {
    XCTFail(@"An exception occured: %@", exception); // you need this, otherwise the test will incorrectly be green.
}
@finally {
    [messageClassMock stopMocking];
}