单元测试 Parse 框架 iOS [英] Unit testing Parse framework iOS

查看:25
本文介绍了单元测试 Parse 框架 iOS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为使用 Parse 后端框架的 iOS 应用程序编写单元测试,经过多次实验,似乎无法编写成功的单元测试.我发现了一些关于测试异步代码的帖子(Testing asynchronous call in unit在 iOS 中测试)并测试网络调用,但我还没有找到一种方法来测试使用异步回调对 Parse 后端的调用.

I am attempting to write unit tests for an iOS application which makes use of the Parse backend framework, and after much experimentation seem to be failing at writing successful unit tests. I have found a few posts on testing asynchronous code (Testing asynchronous call in unit test in iOS) and testing network calls, but am yet to find a way of testing calls to the Parse backend with async callbacks.

举个例子,谁能建议我如何测试以下代码行:

To give an example, could anyone advise how I would test the following line of code:

[PFUser saveUser:userModelMock withBlock:^(BOOL success, NSError *error) {

}];

我正在使用 OCMock 和 XCTest 框架.

I am using OCMock and the XCTest framework.

任何帮助将不胜感激.

* 编辑 *这是我到目前为止所拥有的,但似乎失败了

* EDIT * This is what I have so far but seems to be failing

- (void)testSaveUser {
    id userModelMock = [OCMockObject niceMockForClass:[UserModel class]];
    id userControllerMock = [OCMockObject niceMockForClass:[self.userController class]];

    [[userModelMock expect] saveInBackgroundWithBlock:[OCMArg any]];
    [[userControllerMock stub] saveUser:userModelMock withBlock:[OCMArg any]];

    [userModelMock verify];
}

推荐答案

如果您不介意使用第三方库,您可以使用以下方法:

If you don't mind to utilize a third party library, you may use the following approach:

#import <XCTest/XCTest.h>
#import <RXPromise/RXPromise.h>
...

@interface PFUserTests : XCTestCase
@end

@implementation PFUserTests

// helper:
- (RXPromise*) saveUser:(User*)user {
    RXPromise* promise = [[RXPromise alloc] init];
    [PFUser saveUser:user withBlock:^(Bool success, NSError*error){
        if (success) {
            [promise fulfillWithValue:@"OK"];
        }
        else {
            [promise rejectWithReason:error];
        }
    }];
    return promise;
}


// tests:

-(void) testSaveUser 
{
    User* user = ... ;
    RXPromise* promise = [self saveUser:user];

    // set a timeout:
    [promise setTimeout:5.0];

    [promise.thenOn(dispatch_get_main_queue(), ^id(id result) {
        XCTAssertTrue([result isEqualToString:@"OK"], @"");
        XCTAssertTrue( ... , @"");
        return nil;
    }, ^id(NSError* error) {
        // this may fail either due to a timeout or when saveUser fails:
        XCTFail(@"Method failed with error: %@", error);
        return nil;
    }) runLoopWait];  // suspend the run loop, until after the promise gets resolved 

}

一些注意事项:

您可以在任何队列上执行成功或失败处理程序(使用thenOn语句为promise注册),只需指定队列即可.这不会死锁主线程,即使处理程序在主线程上显式执行,并且测试也在主线程上运行(感谢运行循环机制).

You can execute the success or failure handler (which are registered for the promise with the thenOn statement) on any queue, just specify the queue. This does not dead lock the main thread, even though the handler gets explicitly executed on the main thread, and the test runs as well on the main thread (thanks to the run loop mechanism).

runLoopWait 方法将进入一个运行循环,并且只有在 promise 被解析后才会返回.这既有效又高效.

The method runLoopWait will enter a run loop, and only return once the promise has been resolved. This is both, effective and efficient.

承诺接受超时.如果超时到期,promise 将被拒绝"(即已解决)并出现相应的错误.

A promise accepts a timeout. If the timeout expires, the promise will be "rejected" (that is resolved) with a corresponding error.

IMO,promise 是处理常见异步编程问题的宝贵工具——不仅仅是单元测试的帮手.(另见:维基文章未来和承诺.

IMO, promises are an invaluable tool for handling common asynchronous programming problems - not just a helper for unit tests. (See also: wiki article Futures and promises.

请注意,我是 RXPromise 库 的作者,因此我完全有偏见;)

Please note, I'm the author of the RXPromise library, and thus I'm totally biased ;)

还有其他适用于 Objective-C 的 Promise 实现.

There are other Promise implementations for Objective-C as well.

这篇关于单元测试 Parse 框架 iOS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆