菜鸟教程小白 发表于 2022-12-12 10:40:58

ios - 验证使用两个不同参数调用方法两次


                                            <p><p>我想测试一个方法被调用了两次,第一次传递<code>YES</code>作为参数,第二次传递<code>NO</code>。
使事情复杂化的是我想测试的方法是一个类方法,我不确定这是否与我看到的问题有关。</p>

<p>我的测试如下所示:</p>

<pre><code>- (void)testCreatesMessagesWithCorrectHTMLForcing {
    id messageClassMock = OCMClassMock();
    ;
    [[ andForwardToRealObject] messageForDictionary:
                                                          forceHTMLRendering:YES
                                                                   inContext:];
    [[ andForwardToRealObject] messageForDictionary:
                                                          forceHTMLRendering:NO
                                                                   inContext:];
    NSMutableDictionary *mockJSON = ;
    MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
                                                                     inContext:self.mockContext];
    OCMVerifyAll(messageClassMock);
    ;
}
</code></pre>

<p><code>threadForDictionary:inContext:</code> 方法为线程中的每条消息调用<code>messageForDictionary:forceHTMLRendering:inContext:</code>,并且需要一个对象作为返回值。这就是我添加 <code>andForwardToRealObject</code> 的原因,否则我会因为返回值为 <code>nil</code> 而出现异常。正如您从签名中可以想象的那样,它是关于将 JSON 解析为 CoreData 对象。</p>

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

<pre><code>unexpected method invoked: messageForDictionary:&lt;OCMAnyConstraint: 0x7fab637063d0&gt; forceHTMLRendering:NO inContext:&lt;OCMAnyConstraint: 0x7fab63706eb0&gt;
expected:   messageForDictionary:&lt;OCMAnyConstraint: 0x7fab6371cb20&gt; forceHTMLRendering:YES inContext:&lt;OCMAnyConstraint: 0x7fab6371fb50&gt;&#34;
</code></pre>

<p>我不明白为什么会发生这种情况,因为我最后调用了 <code>stopMocking</code> 所以其他测试不应该受到影响。</p>

<p>以下更改使其他测试正常运行:</p>

<ul>
<li>删除这两个期望中的任何一个。只要只有一个,两者中的哪一个都没有关系。</li>
<li>将方法重命名为 <code>testZ</code>。这样,它在同一文件中的其他测试之后按字母顺序排列;因此,最后执行,似乎不再影响它们。</li>
</ul>

<p>由于 <code>setExpectationOrderMatters:YES</code> 似乎不起作用,我尝试自己检查订单:</p>

<pre><code>- (void)testCreatesMessagesWithCorrectHTMLForcing {
    id messageClassMock = OCMClassMock();
    __block BOOL firstInvocation = YES;
    [[ andForwardToRealObject] messageForDictionary:
                                                          forceHTMLRendering:[OCMArg checkWithBlock:^BOOL (id obj) {
      NSNumber *boolNumber = obj;
      expect().to.equal(firstInvocation);
      firstInvocation = NO;
      return YES;
    }]
                                                                   inContext:];
    NSMutableDictionary *mockJSON = ;
    MyThread *classUnderTest = [MyThread threadForDictionary:mockJSON
                                                                     inContext:self.mockContext];
    expect(firstInvocation).to.equal(NO);
    OCMVerifyAll(messageClassMock);
    ;
}
</code></pre>

<p>但是 <code>checkWithBlock:</code> 似乎没有被调用。 (测试在 <code>expect(firstInvocation).to.equal(NO);</code> 失败)</p>

<p>这是怎么回事?</p>

<p>是否有另一种(更好的?)方法可以使用 OCMock 编写测试,以检查方法是否以正确的顺序使用正确的参数调用?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我终于找到了第一个可行的解决方案。问题是如果 <code>expectationOrderMatters</code> 为 <code>YES</code>,OCMock 会抛出异常。由于异常,测试过早退出,并且永远不会调用 <code>stopMocking</code> ,这会导致无法正确清理模拟。随后对模拟方法的调用将失败,并出现相同的异常,导致所有测试都失败。</p>

<p>解决方案是确保即使一切都出错了也会调用 stopMocking。我通过像这样使用 <code>try-catch</code> 实现了这一点(更改宏并使用 <code>andReturn</code> 而不是 <code>andForwardToRealObject</code> 无关紧要):</p >

<pre><code>MyMessage *message = ;
id messageClassMock = OCMStrictClassMock();
@try {
    ;
    OCMExpect(
                                  forceHTMLRendering:NO
                                           inContext:]).andReturn(message);
    OCMExpect(
                                  forceHTMLRendering:YES
                                           inContext:]).andReturn(message);
    MyThread *classUnderTest = [MyThread threadForDictionary:self.mockJSON
                                                                     inContext:self.mockContext];
    OCMVerifyAll(messageClassMock);
}
@catch (NSException *exception) {
    XCTFail(@&#34;An exception occured: %@&#34;, exception); // you need this, otherwise the test will incorrectly be green.
}
@finally {
    ;
}
</code></pre>

<p>注意catch-block中的<code>XCTFail</code>:你需要包含这个,否则你的测试将会是绿色的,尽管发生了异常。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 验证使用两个不同参数调用方法两次,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/35608314/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/35608314/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 验证使用两个不同参数调用方法两次