26

似乎我第一次在 OCMock 存根上添加andReturnValue时,该返回值是一成不变的。例如:

id physics = [OCMockObject niceMockForClass:[DynamicPhysicsComponent class]
Entity *testEntity = [Entity entityWithPhysicsComponent:physics];
CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];

在 [testEntity update] 中调用存根方法。但是每次存根方法都返回velocity1值,所以我猜第二次尝试设置方法返回值是不值得的。

有没有办法在 OCMock 中做到这一点?

4

4 回答 4

38

当您stub使用一个方法时,您是说它应该始终以指定的方式运行,无论它被调用多少次。解决此问题的最简单方法是更改stub​​为expect

CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics expect] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[[[physics expect] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];

或者,如果您需要stub(例如,如果可能根本不调用该方法),您可以重新创建模拟:

CGPoint velocity1 = CGPointMake(100, 100);
CGPoint velocity2 = CGPointZero;
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity1)] getCurrentVelocity];
[testEntity update:0.1];
[physics verify];

physics = [OCMockObject mockForClass:[Physics class]];
[[[physics stub] andReturnValue:OCMOCK_VALUE(velocity2)] getCurrentVelocity];
[testEntity update:0.1];
[physics verify];
于 2011-04-14T16:56:13.840 回答
28

实际上,当您仅在使用or时stub将返回值设置为石头时。您可以随时使用该方法更改返回值。这是对您需要知道方法将被调用多少次的地方的改进。这是完成此操作的代码片段:andReturnandReturnValueandDoexpect

__weak TestClass *weakSelf = self;
[[[physics stub] andDo:^(NSInvocation *invocation) {
    NSValue *result = [NSValue valueWithCGPoint:weakSelf.currentVelocity];
    [invocation setReturnValue:&result];
}] getCurrentVelocity];
于 2012-11-02T14:20:20.640 回答
2

虽然我认为 CipherCom 有正确的答案,但我发现自己更喜欢创建一个帮助类来返回各种值。我过去遇到过问题NSInvocation

@interface TestHelper : NSObject
@property (nonatomic, assign) CGPoint velocity;
- (CGPoint)getCurrentVelocity;
@end

@implementation TestHelper
- (CGPoint)getCurrentVelocity
{
    return self.velocity;
}
@end

然后在我的测试类中,我将有一个私有成员变量,TestHelper并且在setUp方法中我会这样做:

self.testHelper = [TestHelper new];

[[[physics stub] andCall:@selector(getCurrentVelocity) onObject:self.testHelper]
                 getCurrentVelocity]; 

这样,在我的每个测试中,我都可以将速度设置为我想要的测试速度。

self.testHelper.velocity = CGPointMake(100, 200);

于 2015-03-16T16:59:43.630 回答
1

看起来,andReturn//多次调用时都不会被覆盖andReturnValueandDo我的解决方法是向测试类添加一个属性,并使用它来控制模拟对象应返回的内容。例如,在isAvailable模拟对象上的属性的情况下,我的代码如下所示:

@interface MyTest: XCTestCase 
@property BOOL stubbedIsAvailable;
@end

@implementation MyTest

- (void)setUp {
    [OCMStub([myMockedObject isAvailable]) andDo:^(NSInvocation invocation) {
        BOOL retVal = self.stubbedIsAvailable;
        [invocation setReturnValue:&retVal];
    }
}

- (void)testBehaviourWhenIsAvailable {
    self.stubbedIsAvailable = YES;
    // test the unit
}

- (void)testBehaviourWhenIsNotAvailable {
    self.stubbedIsAvailable = NOT;
    // test the unit
}
于 2016-01-20T14:17:40.117 回答