opensips 模拟呼叫_模拟网络呼叫进行单元测试

opensips 模拟呼叫

两全其美的 (The Best of Both Worlds)

Unit testing is a great way to ensure your app works across many iterations. Sometimes it’s important to ensure things work asynchronously, but also to ensure that you have consistent data. When you don’t control your remote source, this can be virtually impossible.

单元测试是确保您的应用程序可以进行多次迭代的好方法。 有时,确保事物异步运行很重要,但同时也要确保您拥有一致的数据,这一点很重要。 当您不控制远程源时,这几乎是不可能的。

动态环境中的单元测试问题 (The problem with unit testing in a dynamic environment)

If you're unit testing a network call, chances are that you aren’t just testing to make sure that you can connect to the network, but to ensure that you can do something meaningful with it, and perhaps to check that something happens afterwards. That something afterwards usually relies on consistent data.

如果您正在对网络呼叫进行单元测试,则可能不仅是在进行测试以确保可以连接到网络,还在于确保可以对网络做一些有意义的事情,并且可能要检查之后是否发生了某些事情。 。 事后通常依赖于一致的数据。

For example, I want to connect to server A, receive some data, decode the data, then test to make sure the data contains a specific value. That’s an easy enough unit test to write, but there’s an inherent problem in the nature of networking. Things change — and that’s normally a good thing. But when you’re unit testing, you need to rely on things staying the same (such as that specific value from earlier).

例如,我要连接到服务器A,接收一些数据,对数据进行解码,然后进行测试以确保数据包含特定值。 这是编写起来很容易的单元测试,但是网络的本质存在一个固有的问题。 事情发生了变化,这通常是一件好事。 但是,当您进行单元测试时,您需要依靠保持不变的东西 (例如之前的特定值)。

You also need to test your app in as close to an environment as it will be running in when it’s live (i.e. testing in an asynchronous manner). This is impossible with conventional network tests over the long term (unless the data is guaranteed to be static)…

您还需要在应用程序运行时在尽可能接近其运行时的环境中对其进行测试(即以异步方式进行测试)。 长期而言,使用常规网络测试是不可能的(除非保证数据是静态的)…

输入模拟数据加载器 (Enter the Mock Data Loader)

This mock data loader relies on a very simple protocol that very closely mimics URLSession.shared.dataTask. In fact, you can also use this protocol to extend URLSession so that you never forget .resume() again.

该模拟数据加载器依赖于非常简单的协议,该协议非常类似于URLSession.shared.dataTask。 实际上,您还可以使用此协议扩展URLSession,以使您再也不会忘记.resume()

The NetworkLoader protocol
protocol NetworkLoader {    func loadData(using request: URLRequest, with completion: @escaping (Data?, URLResponse?, Error?) -> Void)}

Now that we have our super simple, yet very powerful protocol defined, let’s make a simple class that conforms to it and uses it. This is the class we’ll use for our unit test later. It has the same properties the loadData method takes. It also includes a request property. In this example, the request is private(set) so it can’t be read outside of the class, but it can be set. If you need to change this, you can and it should still function the same.

现在,我们已经定义了超级简单但功能非常强大的协议,让我们创建一个符合它并使用它的简单类。 这是我们稍后将用于单元测试的类。 它具有与loadData方法相同的属性。 它还包括一个request属性。 在此示例中,请求是private(set),因此无法在类外部读取,但可以将其设置。 如果您需要更改此设置,则可以并且它仍应具有相同的功能。

Mock Data Loader
Are you mocking my data???
您在嘲笑我的数据吗???
 class MockDataLoader: NetworkLoader {    let data: Data?
let response: URLResponse?
let error: Error? init(data: Data?, response: URLResponse?, error: Error?) {
self.data = data
self.response = response
self.error = error
} private(set) var request: URLRequest? func loadData(using request: URLRequest, with completion: @escaping (Data?, URLResponse?, Error?) -> Void) {//force this to be async by placing the completion on a background thread DispatchQueue.main.asyncAfter(deadline: .now() + 0.005) {
self.request = request //used to test after this completes
completion(self.data, self.response, self.error)
}
}
}
DispatchQueue.main.asyncAfter makes our call async
This makes our call Asynchronous by putting it on a background thread
通过将其放在后台线程上,可以使我们的调用异步

And let’s make some quick Mock JSON data we can use to decode with the JSONDecoder

让我们快速制作一些可用于通过JSONDecoder解码的Mock JSON数据

Image for post
Using “”” we get a multiline string that we can use special characters in without escaping! We then turn this string into data, being careful to make sure the JSON string is formatted correctly.
使用“”,我们得到一个多行字符串,可以在其中使用特殊字符而不会转义! 然后,我们将此字符串转换为数据,请注意确保JSON字符串的格式正确。
let data = """
{
"money":"1,000"
}
""".data(using: .utf8)!

Now lets write a test that loads this data, decodes the value of “money” (“1,000”) and checks to see if we can convert that to an Int

现在,让我们编写一个测试来加载此数据,解码“ money”(“ 1,000”)的值,并检查是否可以将其转换为Int

Remember, to write an asynchronous unit test, we’ll need to use an expectation or our test won’t work… even though the test will report that it succeeded, it didn’t actually do the asynchronous part.

记住,要编写一个异步单元测试,我们需要使用期望值,否则我们的测试将无法正常工作……即使测试报告成功,但实际上并没有完成异步部分。

Unit test testing the mock data we just created
Are you mocking unit testing??
您在模拟单元测试吗?
func testDecodingMockData() {    let expectation = self.expectation(description: "\(#file), \(#function): WaitForDecodingMockData")    //using the data constant we just created
let mockDataLoader = MockDataLoader(
data: data,
response: nil,
error: nil
) let request = URLRequest(url: URL(string: "www.google.com")!) mockDataLoader.loadData(using: request) { (data, nil, error) in
XCTAssertNotNil(mockDataLoader.data) XCTAssertNil(mockDataLoader.response)
XCTAssertNil(mockDataLoader.error)
let decoder = JSONDecoder() let dictionary = try? decoder.decode([String:String].self, from: mockDataLoader.data!)
let money = dictionary?["money"]
XCTAssertNotNil(Int(money!))
expectation.fulfill()
}wait(for: [expectation], timeout: 1.0)}

And just like that, we’ve written a consistent test that mocks the state of our app and proves that we can convert a String to an Int. The test runs asynchronously, so we can test that other functions would fire after this one completes among other things.

就像这样,我们编写了一个一致的测试来模拟应用程序的状态,并证明我们可以将String转换为Int。 该测试异步运行,因此我们可以测试该功能完成后是否会触发其他功能。

As I mentioned earlier, it can also be used to extend URLSession. As such, I can make a class with this property and use it to switch between live and mock data on the fly.

如前所述,它也可以用于扩展URLSession。 这样,我可以使用此属性创建一个类,并使用它在实时数据和模拟数据之间进行切换。

Image for post
a class with this property and initializer will use a live URLSession by default, but allow you to override the dataLoader with a MockDataLoader
具有此属性和初始化程序的类将默认使用实时URLSession,但允许您使用MockDataLoader覆盖dataLoader
class NetworkService {
///used to switch between live and Mock Data
var dataLoader: NetworkLoader init(dataLoader: NetworkLoader = URLSession.shared) {
self.dataLoader = dataLoader
}
}

翻译自: https://medium.com/swlh/unit-testing-with-mock-network-calls-b7fe3af0bca5

opensips 模拟呼叫

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值