如何使用 OCMock 3 在单元测试中检查函数的返回值

Posted

技术标签:

【中文标题】如何使用 OCMock 3 在单元测试中检查函数的返回值【英文标题】:how to check the return value of a function in unit test with OCMock 3 【发布时间】:2016-05-31 14:36:43 【问题描述】:

我正在使用OCMock 3 在我的 ios 项目中进行单元测试。

OCMock 被称为 iOS 的一个很棒的单元测试库,但是我上面链接的 OCMock 文档并没有明确说明如何检查函数的返回值,它一直都在说明如何存根函数返回并验证它。 但我不想存根该函数返回,我需要检查真正的返回值。

例如,我想对我的School 类的一个函数进行单元测试:

@implementation School
...
- (void) checkStudents 
  BOOL isOnVacation = [[Coordinator sharedInstance] checkCalendar];
  if (!isOnVacation) 
     takeLecture();
  

@end 

我的测试用例:

- (void) testCheckStudents 
    // create a partially mocked 'Coordinator' instance
    id coordinatorMock = [OCMockObject partialMockForObject:[Cooridnator sharedInstance]];

    // run the method under test
    [schoolToTest checkStudents];

    // I want to check not only '[[Coordinator sharedInstance] checkCalendar]' is invoked, but also check its return value is YES. How to check this in OCMock?
    OCMVerify([coordinatorMock checkCalendar]);

我不想存根[[Coordinator sharedInstance] checkCalendar] 的返回值,而是运行真正的实现。

我不仅要检查[[Coordinator sharedInstance] checkCalendar]是否被调用,还要检查它的返回值是YES。如何在 OCMock 中检查这个?

(通过它的文档,我只能看到存根函数在此处和那里返回,然后验证该函数是否被调用。我是否遗漏了它的文档中的某些内容?)

【问题讨论】:

【参考方案1】:

验证[[Coordinator sharedInstance] checkCalendar] 的返回值不在此案例的范围内,因为您的单元测试正在验证School 的行为。模拟对象背后的想法是能够假设您正在测试的对象以外的对象都按预期运行。

您在当前状态下的测试是完美的——您只是在假设Coordinator 的行为与预期完全一样的情况下,在默认条件下调用checkStudents 时验证checkCalendar 被调用。

如果你想验证checkCalendar的返回值,你应该在CoordinatorTests中写一个单独的测试方法测试它在各种条件下的返回值:

// CalendarTests.m

- (void) testCheckCalendar

    // Do some setup to mock the conditions created by checkStudents

.
.    
.

    // Verify
    XCTAssertEqual([[Cooridnator sharedInstance] checkStudents], YES);

【讨论】:

这是正确答案。您应该为checkStudents 编写一个测试。这是你所拥有的。您应该为checkCalendar 编写一个单独的测试,而对于该测试,您可能根本不需要OCMock;只需调用该方法并对返回值进行断言即可。

以上是关于如何使用 OCMock 3 在单元测试中检查函数的返回值的主要内容,如果未能解决你的问题,请参考以下文章

使用 OCMock 和 MagicalRecord 进行单元测试

xcode 中的单元测试(使用 GHUnit 和 OCMock)

IOS单元测试,OCMock

void 方法的 OCMock 测试

使用 OCMock 静态库进行 iOS 单元测试(-ObjC 标志问题)

如何使用OCMock验证在Objective C中不调用异步方法?