OCMock单元测试错误

时间:2014-08-31 01:31:48

标签: ios objective-c unit-testing ocmock xctest

我使用OCMock测试单例方法。我得到了#34;模拟类中没有这样的方法。" testSingleton方法的错误和testSingletonWithBlock方法的无限循环(屏幕截图,旋转指示符)

编辑: 在这里下载示例项目

https://drive.google.com/file/d/0B-iP0P7UfFj0LVFpWWpPb3RDZFU/edit?usp=sharing

enter image description here

这是我的实施

经理:

@implementation Manager
+ (Manager *)sharedManager {
    static Manager *instance;
    dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        instance = [Manager new];
    });
    return instance;
}
- (int)getOne {
    return 1;
}
- (void)success:(BOOL)success completion:(void(^)(void))completion failure:(void(^)(void))failure {
    success ? completion() : failure();
}

查看控制器:

- (void)manager_printOne {
    int num = [[Manager sharedManager] getOne];
    NSLog(@"number is: %d", num);
}

- (void)manager_success:(BOOL)success completion:(void(^)(void))completion failure:(void(^)(void))failure {

    [[Manager sharedManager] success:success completion:completion failure:failure];

}

测试视图控制器:

@interface coreDataTestTests : XCTestCase

@property (nonatomic, strong) id mockManager;

@property (nonatomic, strong) ViewController *viewController;

@end

@implementation coreDataTestTests

- (void)setUp
{
    [super setUp];

    self.viewController = [ViewController new];

    //for singleton
    self.mockManager = [Manager createNiceMockManager];
}

- (void)tearDown
{
    [super tearDown];

    self.viewController = nil;


    //Note: singleton need both, retain counts = 2
    self.mockManager = nil;
    [Manager releaseInstance];

}



- (void)testSingleton {

    NSLog(@"testSingleton");
    OCMStub([self.mockManager getOne]).andReturn(2);
    [self.viewController manager_printOne];

}



- (void)testSingletonWithBlock {

    NSLog(@"testSingletonWithBlock");

    [[[[self.mockHelper stub] ignoringNonObjectArgs] andDo:^(NSInvocation *invocation) {

        void(^block)(void);

        [invocation getArgument:&block atIndex:3];
        block();

    }] success:0 completion:[OCMArg any] failure:[OCMArg any]];


    [self.viewController manager_success:NO completion:^{
        NSLog(@"completion");
    } failure:^{
        NSLog(@"failure");
    }];



}




@end

单元测试的经理类别:

static Manager *mockManager = nil;

@implementation Manager

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

+ (Manager *)sharedManager {
    if (mockManager) {
        return mockManager;
    }
    return invokeSupersequentNoParameters();
}



#pragma clang diagnostic pop

+(id)createMockManager {
    mockManager = [OCMockObject mockForClass:[Manager class]];
    return mockManager;
}

+(id)createNiceMockManager {
    mockManager = [OCMockObject niceMockForClass:[Manager class]];
    return mockManager;
}

+(void)releaseInstance {
    mockManager = nil;
}

2 个答案:

答案 0 :(得分:3)

而不是创建一个类别,你可以只是存根sharedManager并返回一个漂亮的模拟。

- (void)setUp
{
    [super setUp];

    self.viewController = [ViewController new];

    //for singleton
    id classMockManager = OCClassMock([Manager class]);
    OCMStub([classMockManager sharedManager]).andReturn(classMockManager);
    self.mockManager = classMockManager;
}

我现在没有一个环境来测试这个,但这个策略应该有效。请注意,这是OCMock3语法。见http://ocmock.org/reference/#mocking-class-methods

答案 1 :(得分:1)

在上面的描述中,您编写了“单元测试的管理器类别”,但后面的实现不是一个类别,它是Manager类的实际实现,即代码读取

@implementation Manager

而不是

@implementation Manager(unitTests)

测试代码似乎使用了Manager的第二个实现,并且该实现没有getOne方法。所以模仿是抱怨的权利;它看到的Manager的实现没有方法,因此它不能存根。

我相信你可以通过将实现作为一个类别来修复你的测试。据我所知,可以在类别中覆盖类方法(在您的情况下为sharedManager),但这样做有点冒险。 Ben Flynn描述的方法更好。