我有以下单元测试失败。我认为它是因为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];
}
threadedRequestToCallMethodA
中的{p> callMethodAFromTestClassC
和TestClassC
定义如下:
- (void) threadedRequestToCallMethodA
{
[NSThread detachNewThreadSelector:@selector(callMethodAFromTestClassC) toTarget:self withObject:nil];
}
- (void) callMethodAFromTestClassC
{
[[[TestClassA alloc] init] testMethodA];
}
testMethodA
中的 TestClassA
定义为:
- (void) testMethodA
{
NSLog(@"testMethodA");
}
Stub方法定义如下:
- (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;
}
感谢您的帮助。
感谢。
答案 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