Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何更改OCMock存根的返回值?_Unit Testing_Ocmock - Fatal编程技术网

Unit testing 如何更改OCMock存根的返回值?

Unit testing 如何更改OCMock存根的返回值?,unit-testing,ocmock,Unit Testing,Ocmock,似乎我第一次在OCMock存根上添加andReturnValue时,返回值是一成不变的。例如: id physics = [OCMockObject niceMockForClass:[DynamicPhysicsComponent class] Entity *testEntity = [Entity entityWithPhysicsComponent:physics]; CGPoint velocity1 = CGPointMake(100, 100); CGPoint velocity2

似乎我第一次在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中是否有这样做的方法?

当您
存根
一个方法时,您是说它应该始终以指定的方式运行,无论调用多少次。解决此问题的最简单方法是将
存根
更改为
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];
或者,如果需要
存根
(例如,如果可能根本不调用该方法),则可以重新创建模拟:

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];

实际上,当您使用
stub
时,如果您使用
andReturn
andReturnValue
,则您只需在石头上设置返回值。您可以使用方法
和do
随时更改返回值。这是对
expect
的改进,您需要知道一个方法将被调用多少次。下面是完成此操作的代码片段:

__weak TestClass *weakSelf = self;
[[[physics stub] andDo:^(NSInvocation *invocation) {
    NSValue *result = [NSValue valueWithCGPoint:weakSelf.currentVelocity];
    [invocation setReturnValue:&result];
}] getCurrentVelocity];

虽然我认为CipherCom有正确的答案,但我发现自己更喜欢创建一个helper类来返回各种值。我过去曾遇到过
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(100200)

看起来在多次调用时都不会被覆盖。我的解决方法是向测试类添加一个属性,并使用该属性控制模拟对象应返回的内容。例如,在模拟对象上的
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
}

我懂了。我没有使用expect,因为我不需要验证,但是使用它来更改模拟方法的行为(如第一个示例中所示)对于我的案例非常有效。谢谢。在第二个示例中,当与存根方法一起使用时,
verify
的目的是什么?我认为verify可能没有必要。我只是想指出,在为模拟分配新的模拟之前,您需要在模拟上调用verify(如果适合您的测试,比如是否有其他期望)。对于任何出现错误的人
没有像我这样的选择器“expect”的已知实例方法,您需要将存根强制转换为
OCMockObject*
。我更喜欢这个答案,因为您没有强制执行必须调用存根方法多少次(如预期的那样)。