Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/113.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.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
Ios 如何对NSURLConnection委托进行单元测试?_Ios_Unit Testing_Nsurlconnection_Ocmock_Nsurlconnectiondelegate - Fatal编程技术网

Ios 如何对NSURLConnection委托进行单元测试?

Ios 如何对NSURLConnection委托进行单元测试?,ios,unit-testing,nsurlconnection,ocmock,nsurlconnectiondelegate,Ios,Unit Testing,Nsurlconnection,Ocmock,Nsurlconnectiondelegate,如何对NSURLConnection委托进行单元测试? 我创建了一个符合不同协议的ConnectionLegate类,将数据从web服务到不同的ViewController。在我走得太远之前,我想开始编写我的单元测试。 但是我不知道如何在没有互联网连接的情况下测试它们。我还想知道如何处理异步回调。以下是我应该做的: 获取XAMPP控制面板 启动apache服务器 在您的~/Sites文件夹中,放置一个测试文件(无论您需要什么数据,我们都将其称为my file.test) 使用URL启动您的代理

如何对NSURLConnection委托进行单元测试? 我创建了一个符合不同协议的ConnectionLegate类,将数据从web服务到不同的ViewController。在我走得太远之前,我想开始编写我的单元测试。 但是我不知道如何在没有互联网连接的情况下测试它们。我还想知道如何处理异步回调。

以下是我应该做的:

  • 获取XAMPP控制面板
  • 启动apache服务器
  • 在您的
    ~/Sites
    文件夹中,放置一个测试文件(无论您需要什么数据,我们都将其称为
    my file.test
  • 使用URL启动您的代理
  • 不使用apache服务器时停止它

  • 我在单元测试中避免联网。相反:

    • 我在一个方法中隔离NSURLConnection
    • 我创建了一个测试子类,覆盖该方法以删除NSURLConnection的所有跟踪
    • 我编写了一个测试,以确保在需要时调用所讨论的方法。然后我知道它会在现实生活中引发一种联系

    然后我将重点放在更有趣的部分:合成具有各种特征的模拟NSURL响应,并将它们传递给NSURLConnectionLegate方法。

    我最喜欢的方法是将NSURLProtocol子类化,并让它响应所有http请求或其他协议。然后在
    -setup
    方法中注册测试协议,并在
    -tearDown
    方法中取消注册。 然后,您可以让这个测试协议将一些众所周知的数据返回到您的代码中,以便您可以在单元测试中验证它

    我写了一些关于这个主题的博客文章。与您的问题最相关的可能是和


    您可能还想看看我的ILCannedURLProtocol,这在前面的文章中有介绍。该消息来源于。

    这与Jon的回答类似,但无法将其纳入评论中。第一步是确保您没有创建真正的连接。实现这一点的最简单方法是将连接的创建拉入工厂方法,然后在测试中替换工厂方法。有了OCMock的部分mock支持,这可能看起来像这样

    在你真正的课堂上:

    - (NSURLConnection *)newAsynchronousRequest:(NSURLRequest *)request
    {
        return [[NSURLConnection alloc] initWithRequest:request delegate:self];
    }
    
    在您的测试中:

    id objectUnderTest = /* create your object */
    id partialMock = [OCMockObject partialMockForObject:objectUnderTest];
    NSURLConnection *dummyUrlConnection = [[NSURLConnection alloc] 
        initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"file:foo"]] 
        delegate:nil startImmediately:NO];
    [[[partialMock stub] andReturn:dummyUrlConnection] newAsynchronousRequest:[OCMArg any]];
    
    现在,当您的被测对象尝试创建URL连接时,它实际上获得了在测试中创建的虚拟连接。虚拟连接不必是有效的,因为我们没有启动它,而且它从未被使用过。如果代码确实使用了该连接,则可以返回另一个模拟,即模拟NSURLConnection的模拟

    第二步是调用对象上触发创建NSURLConnection的方法:

    [objectUnderTest doRequest];
    
    因为被测试对象没有使用真正的连接,我们现在可以从测试中调用委托方法。对于我们正在使用另一个模拟的NSURLResponse,响应数据是从测试中其他地方定义的字符串创建的:

    int statusCode = 200;
    id responseMock = [OCMockObject mockForClass:[NSHTTPURLResponse class]];
    [[[responseMock stub] andReturnValue:OCMOCK_VALUE(statusCode)] statusCode];
    [objectUnderTest connection:dummyUrlConnection didReceiveResponse:responseMock];
    
    NSData *responseData = [RESPONSE_TEXT dataUsingEncoding:NSASCIIStringEncoding];
    [objectUnderTest connection:dummyUrlConnection didReceiveData:responseData];
    
    [objectUnderTest connectionDidFinishLoading:dummyUrlConnection];
    
    就这样。您已经有效地伪造了被测试对象与连接之间的所有交互,现在您可以检查它是否处于应该处于的状态

    如果希望看到一些“真实”代码,请查看使用NSURLConnections的CCMenu项目中的类的测试。这有点令人困惑,因为被测试的类也被命名为connection

    编辑(2014年2月18日):我偶然发现这篇文章提供了一个更优雅的解决方案

    基本上,您有以下方法:

    - (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;
    }
    
    基本格式:

    - (void)testAsync
    {
        // 1. Call method which executes something asynchronously 
        [obj doAsyncOnSuccess:^(id result) {
            STAssertNotNil(result);
            done = YES;
        }
        onError:^(NSError *error) [
            STFail();
            done = YES;
        }
    
        // 2. Determine timeout
        STAssertTrue([self waitForCompletion:5.0], @"Timeout");
    }    
    
    ==============

    我参加聚会迟到了,但我遇到了一个非常简单的解决办法。(非常感谢)

    .h文件:

    @property (nonatomic) BOOL isDone;
    
    .m文件:

    - (void)testAsynchronousMethod
    {
        // 1. call method which executes something asynchronously.
    
        // 2. let the run loop do its thing and wait until self.isDone == YES
        self.isDone = NO;
        NSDate *untilDate;
        while (!self.isDone)
        {
            untilDate = [NSDate dateWithTimeIntervalSinceNow:1.0]
            [[NSRunLoop currentRunLoop] runUntilDate:untilDate];
            NSLog(@"Polling...");
        }
    
        // 3. test what you want to test
    }
    
    在异步方法正在执行的线程中,
    isDone
    设置为
    YES

    因此,在本例中,我在步骤1创建并启动了NSURLConnection,并使其委托成为这个测试类。在

    -(void)连接:(NSURLConnection*)连接didReceiverResponse:(nsurResponse*)响应


    我设置
    self.isDone=YES。我们打破while循环,执行测试。完成。

    您可能想给这个机会:

    下面是正在进行单元测试的NSURLConnection的一些示例代码:

    在我的委托方法中模拟或存根NSURLConnection怎么样?我将NSURLConnection子类化,以包含接收到的NSData、接收器(我将编写的JSON获取程序)以及用于调用它的请求。在查看我的代码并再次阅读您的答案后,我发现我的思路是正确的!我的NSURLConnection已在方法-(void)sendRequest:(NSURLRequest*)request for receiver:(id)receiver中隔离。我可以测试所有其他方法,以确保URL和请求的格式良好。另一方面,通过重写sendRequest方法,我可以传递假数据来测试我的接收器。这有意义吗?我读了这两篇文章,它们都很有趣。多亏了他们,我才开始有了解决这个问题的想法。我不认为我需要将NSURLProtocol子类化(如果将来发生变化,我更不愿意这样做),因为我的连接委托不处理数据。我用我的接收器作为观察者。因此,通过重写启动连接的方法,我可以提供所需的数据。附言:很棒的博客!我已将IL添加到书签中;)谢谢你的评论。只是澄清一下,ILCannedURLProtocol并不是为了在生产代码中找到它的方式,所以我不会太担心底层NSURL协议的更改。如果发生这种情况,那仅仅是对测试设置的更改。与您的方法配合得非常好。这将响应限制为404、200和无响应。如果您想测试、冲突409、204、403以及其他状态代码、ETag、压缩等等,该怎么办。。。另外,如果您使用的是自动构建服务器,您会不会
    - (void)testAsynchronousMethod
    {
        // 1. call method which executes something asynchronously.
    
        // 2. let the run loop do its thing and wait until self.isDone == YES
        self.isDone = NO;
        NSDate *untilDate;
        while (!self.isDone)
        {
            untilDate = [NSDate dateWithTimeIntervalSinceNow:1.0]
            [[NSRunLoop currentRunLoop] runUntilDate:untilDate];
            NSLog(@"Polling...");
        }
    
        // 3. test what you want to test
    }