OHHTTPStubs 不是存根主机?

Posted

技术标签:

【中文标题】OHHTTPStubs 不是存根主机?【英文标题】:OHHTTPStubs not stubbing host? 【发布时间】:2015-10-01 04:36:25 【问题描述】:

如果 ios 应用程序有自己的请求,OHHTTPStubs 不会模拟请求?

如果 App 在测试运行之前发出任何 Alamofire 请求,OHHTTPStubs 将不会在单元测试中模拟任何请求

OHHTTPStubs 4.3.0 with swift support Alamofire 2.0.2

测试文件 - 按预期工作

stub(isHost("httpbin.org"))  _ in
    let stubData = "Hello World!".dataUsingEncoding(NSUTF8StringEncoding)
    return OHHTTPStubsResponse(data: stubData!, statusCode:200, headers:nil)


print("@@Start")
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
    .responseString()  request, response, data in
        print(data)

但是,一旦将以下内容添加到 AppDelegate.swift,它就不再起作用,而是向服务发出实际的 HTTP 请求

Alamofire.request(.GET, "http://httpbin.org/get")
    .responseString()  request, response, data in
            print(data)


原始问题留给后代

更新:我在一个干净的项目中再次尝试,它按预期工作,所以肯定有其他事情发生。

在 swift 2.0 的最新升级中,OHHTTPStubs 没有对请求进行存根处理,而是通过并实时调用它们。

我在单元测试中设置了一个简短的示例,但它仍然通过。我错过了什么?

import Foundation
import Quick
import Nimble
import Alamofire
import OHHTTPStubs

class RequestsSpec: QuickSpec 
var data:Result<String>? = nil

override func spec() 
    describe("the request") 
        it("needs to make a request") 

            stub(isHost("httpbin.org"))  _ in
                let stubData = "Hello World!".dataUsingEncoding(NSUTF8StringEncoding)
                return OHHTTPStubsResponse(data: stubData!, statusCode:200, headers:nil)
            

            Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
                .responseString()  request, response, data in
                    print(request)
                    print(response)
                    print(data)
                    print(data.value)
                    self.data = data
            
            expect(self.data).toEventuallyNot(beNil(), timeout: 3)
        
    

我明白了

Optional(<NSMutableURLRequest: 0x7f91598e22e0>  URL: http://httpbin.org/get?foo=bar )
Optional(<NSHTTPURLResponse: 0x7f915da8c220>  URL: http://httpbin.org/get?foo=bar   status code: 200, headers 
    "Access-Control-Allow-Credentials" = true;
    "Access-Control-Allow-Origin" = "*";
    Connection = "keep-alive";
    "Content-Length" = 364;
    "Content-Type" = "application/json";
    Date = "Thu, 01 Oct 2015 04:19:42 GMT";
    Server = nginx;
 )
Optional("\n  \"args\": \n    \"foo\": \"bar\"\n  , \n  \"headers\": \n    \"Accept\": \"*/*\", \n    \"Accept-Encoding\": \"gzip;q=1.0,compress;q=0.5\", \n    \"Accept-Language\": \"en-US;q=1.0\", \n    \"Host\": \"httpbin.org\", \n    \"User-Agent\": \"ios-consumer-app/com.dante.ouli2 (28; OS Version 9.0 (Build 13A340))\"\n  , \n  \"url\": \"http://httpbin.org/get?foo=bar\"\n\n")

而不是 Hello World!

我尝试使用 NSURLSession 发出请求,并且 OHHTTPStubs 正常工作。 OHHTTPStubs/Alamofire 交互似乎有问题?

            let url = NSURL(string: "http://httpbin.org/get")

            let task = NSURLSession.sharedSession().dataTaskWithURL(url!) (data, response, error) in
                print(NSString(data: data!, encoding: NSUTF8StringEncoding))
                self.data2 = data
            
OHHTTPStubs 4.3.0 支持 swift Alamofire 2.0.2

【问题讨论】:

【参考方案1】:

当您运行应用程序/UI 测试时,Xcode 在模拟器中启动应用程序,将测试包作为插件加载,然后在应用程序内执行单元测试。

实际的应用程序和测试包都加载到内存中。如果您将 OHHTTPStubs 与 App 目标和 Test 目标链接,则该库将被加载两次,并且将在内存中加载两个实例。这会导致您的测试包中的存根无法拦截应用内的请求。

如果可能,请避免将 OHHTTPStubs 链接到测试目标(您的应用),以便它只加载一次。

如果您确实需要在测试目标中包含 OHHTTPStubs,您可以在测试设置期间附加一个类似于标志的字符串到 launchEnvironment。然后通过 NSProcessInfo.processInfo().environment["SOME_STRING_FLAG"] 检查您的应用程序内部是否存在标志。

有关此问题的更多信息,请阅读 AliSoftware 的关于此问题的 wiki:https://github.com/AliSoftware/OHHTTPStubs/wiki/A-tricky-case-with-Application-Tests

【讨论】:

我用 OHHTTPStubs 创建者开了一张票,结果发现它是 Alamofire 和 OHHTTPStubs github.com/AliSoftware/OHHTTPStubs/issues/126 分辨率之间的一个边缘案例列在线程的底部【参考方案2】:

使用 OHHTTPStubs 打开了一张票。这是 Alamofire 和 OHHTTPStubs 之间的边缘案例

https://github.com/AliSoftware/OHHTTPStubs/issues/126 分辨率在底部的最后两篇文章中

修复边缘情况的一些想法:

切换到非托管测试,以便在加载测试包之前不会启动您的应用 保留托管测试,但将 OHHTTPStubs 添加到您的应用程序包而不是测试包,以便在运行测试时启动应用程序时立即加载它 以某种方式破解您的 AppDelegate 代码,这样当从测试启动时,它不会对 Alamofire.request 进行任何调用,并且 Alamofire 在应用程序或测试中发出的第一个请求(从而触发它对创建其内部 NSURLSessionConfiguration 的 Manager.sharedInstance)仅在测试包被加载并注入您的应用包后完成。

我最终做了什么

我已经做到了,所以在启动期间不会发出 Alamofire 请求

【讨论】:

以上是关于OHHTTPStubs 不是存根主机?的主要内容,如果未能解决你的问题,请参考以下文章

OHHTTPStubs 单元测试实现

让 Alamofire 和 OHHTTPStubs 一起工作

是否可以在 Xcode 7 自动化 UI 测试中存根 HTTP 请求?

使用 OHHTTPStubs 模拟时未达到 Alamofire 响应块

java 里的 stub 是啥??

2016.9.9 网络工程师之路由器技术