Objective c 如何使用OCMock在不同的线程上正确地存根方法?

Objective c 如何使用OCMock在不同的线程上正确地存根方法?,objective-c,unit-testing,ocmock,Objective C,Unit Testing,Ocmock,下面的单元测试失败了。我认为这是因为,OCMock在多个线程中不能很好地工作,但我可能错了mockTestMethodA永远不会被调用。如果我修改代码,在同一个线程上调用testMethodA(没有NSThread),存根似乎可以工作。这是OCMock的已知限制还是我遗漏了什么 示例代码: - (void) testCallMethodUsingNSThreadFromADifferentClass { mockTestClassA = [OCMockObject partialMockF

下面的单元测试失败了。我认为这是因为,
OCMock
在多个线程中不能很好地工作,但我可能错了
mockTestMethodA
永远不会被调用。如果我修改代码,在同一个线程上调用
testMethodA
(没有
NSThread
),存根似乎可以工作。这是
OCMock
的已知限制还是我遗漏了什么

示例代码:

- (void) testCallMethodUsingNSThreadFromADifferentClass
{
   mockTestClassA = [OCMockObject partialMockForObject:testClassA];

   [[[mockTestClassA expect] andCall:@selector(mockTestMethodA) onObject:self] testMethodA];

   [testClassC threadedRequestToCallMethodA];

   [self waitForCompletion:5.0];

   [mockTestClassA verify];
}
TestClassC
中的
threadedRequestToCallMethodA
callMethodAFromTestClassC
定义如下:

- (void) threadedRequestToCallMethodA
{
    [NSThread detachNewThreadSelector:@selector(callMethodAFromTestClassC) toTarget:self withObject:nil];
}

- (void) callMethodAFromTestClassC
{
    [[[TestClassA alloc] init] testMethodA];
}
- (void) mockTestMethodA
{
   NSLog(@"mockTestMethodA");
}
TestClassA
中的
testMethodA
定义为:

- (void) testMethodA
{
    NSLog(@"testMethodA");
}
存根方法定义如下:

- (void) threadedRequestToCallMethodA
{
    [NSThread detachNewThreadSelector:@selector(callMethodAFromTestClassC) toTarget:self withObject:nil];
}

- (void) callMethodAFromTestClassC
{
    [[[TestClassA alloc] init] testMethodA];
}
- (void) mockTestMethodA
{
   NSLog(@"mockTestMethodA");
}
最后,
waitForCompletion

- (BOOL) waitForCompletion:(NSTimeInterval)timeoutSecs
{
    NSDate  *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];
    do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
        if([timeoutDate timeIntervalSinceNow] < 0.0)
        break;
    } while (!done);

   return done;
 }
-(BOOL)等待完成:(NSTimeInterval)超时秒
{
NSDate*timeoutDate=[NSDate DATE WITH TIMEINTERVALICENCENOW:TIMEOUTECS];
做{
[[NSRunLoop currentRunLoop]运行模式:NSDefaultRunLoopMode beforeDate:timeoutDate];
如果([timeoutDate TimeIntervalenceNow]<0.0)
打破
}而(!完成);
已完成的返回;
}
谢谢你的帮助


谢谢。

您的问题是,您没有对部分模拟的对象调用测试方法,而是在
callMethodAFromTestClassC
中分配一个新方法。如果你在适当的对象上调用它,它工作得很好。请参见下文(注意,我实际上并没有创建单独的C类,但效果是相同的)。作为旁注,我认为积木和GCD让生活更轻松,但每个人都有自己的风格

//
//  TestClassTest.m
//  TestApp
//
//  Created by Benjamin Flynn on 11/20/12.
//

#import <SenTestingKit/SenTestingKit.h>
#import "OCMock.h"
#import "TestClassA.h"

@interface TestClassTest : SenTestCase

@property (nonatomic, retain) TestClassA *testClassA;
@property (atomic, assign) BOOL done;
@end


@implementation TestClassTest

- (void) testCallMethodUsingNSThreadFromADifferentClass
{
    self.testClassA = [[TestClassA alloc] init];
    id mockTestClassA = [OCMockObject partialMockForObject:self.testClassA];
    [[[mockTestClassA expect] andCall:@selector(mockTestMethodA) onObject:self] testMethodA];
    [self threadedRequestToCallMethodA];
    [self waitForCompletion:5.0];    
    [mockTestClassA verify];
}

- (void)threadedRequestToCallMethodA
{
    [NSThread detachNewThreadSelector:@selector(callMethodAFromTestClassC) toTarget:self withObject:nil];
}


- (void)callMethodAFromTestClassC
{
    [self.testClassA testMethodA];
}

- (void)mockTestMethodA
{
    NSLog(@"Mock test method A");
    self.done = YES;
}

- (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs
{
    NSDate  *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];
    NSLog(@"Starting timer");
    do {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
        if([timeoutDate timeIntervalSinceNow] < 0.0)
            break;
    } while (!self.done);
    NSLog(@"Ending timer");

    return self.done;
}

@end
//
//TestClassTest.m
//特斯塔普
//
//本杰明·弗林于2012年11月20日创作。
//
#进口
#导入“OCMock.h”
#导入“TestClassA.h”
@接口TestClassTest:SenTestCase
@属性(非原子,保留)TestClassA*TestClassA;
@属性(原子、赋值)BOOL done;
@结束
@实现TestClassTest
-(void)testCallMethodUsingNSThreadFromADifferentClass
{
self.testClassA=[[testClassA alloc]init];
id mockTestClassA=[OCMockObject partialMockForObject:self.testClassA];
[[[mockTestClassA expect]和call:@selector(mockTestMethodA)onObject:self]testMethodA];
[自线程请求调用方法A];
[自我等待完成:5.0];
[mockTestClassA验证];
}
-(无效)ThreadedRequestToCall方法A
{
[NSThread detachNewThreadSelector:@selector(callMethodAFromTestClassC)toTarget:self with Object:nil];
}
-(无效)callMethodAFromTestClassC
{
[self.testClassA testMethodA];
}
-(void)mockTestMethodA
{
NSLog(“模拟试验方法A”);
self.done=是;
}
-(BOOL)等待完成:(NSTimeInterval)超时秒
{
NSDate*timeoutDate=[NSDate DATE WITH TIMEINTERVALICENCENOW:TIMEOUTECS];
NSLog(“启动计时器”);
做{
[[NSRunLoop currentRunLoop]运行模式:NSDefaultRunLoopMode beforeDate:timeoutDate];
如果([timeoutDate TimeIntervalenceNow]<0.0)
打破
}而(!self.done);
NSLog(“结束计时器”);
返回自我完成;
}
@结束