断言当前线程是主线程的单元测试[iOS]

时间:2018-12-14 06:17:53

标签: ios swift multithreading unit-testing testing

问题是编写一个断言当前线程是主线程的单元测试有意义吗? 优点/缺点?

最近,我看到了单元测试,该单元测试为服务的回调声明了当前线程。我不确定这是个好主意,我相信这是一种更多的集成测试。我认为,单元测试应该孤立地声明方法,并且不应该了解服务使用者的性质。

在iOS中,此服务的使用者旨在成为一个UI,默认情况下,它具有在主线程上运行代码的约束。

更新:

服务内部有一个电话:

DispatchQueue.main.async {
    failure(error)
}

它在测试套件中运行,并且没有被模拟。因此,有一个 delay 违反了以下规则:单元测试必须快速并且单元测试应与任何其他单元测试同时运行。

3 个答案:

答案 0 :(得分:1)

这是UI层的工作,以确保它仅更新主线程上的UI。您希望将主线程上的工作限制到最低限度(基本上,仅UI工作)。您的回调很可能会做很多其他处理。仅将这些全部放在主线程上是不好的做法,因为仅这些任务的一小部分(UI更改)需要它。

答案 1 :(得分:1)

IMO,从单元测试的角度来看,我们不应该集中精力测试当前正在运行的线程。编写测试用例的目的是确保源代码的单个单元能够正常工作,因此,我们应该专注于结果而不是关心其他任何依赖层(服务)功能;这就是在单元测试中存在 mocking 概念的原因!如果SUT(被测系统)使用处理异步任务的服务,则应对其进行模拟,我们将再次专注于测试特定的源代码单元。

作为一个现实示例,如果我们有一个依赖于网络层MyViewController的视图控制器NetworkingManager,如下所示:

class MyViewController: UIViewController {
    let networkManager = NetworkManager()

    func doSomething() {
        networkManager.getWhatever { isSuccess in
            // here is the side effect
        }
    }
}

class NetworkManager {
    func getWhatever(callback: (Bool) -> Void) {
        //...
    }
}

当打算测试doSomething时,我们不必关心getWhatever方法,因此我们模拟NetworkManager并为我们的测试提供适当的实现; getWhatever回调在哪个线程上运行都没有关系,相反,这里的断言是doSomething从{{1}成功或失败时所产生的副作用},而无需考虑其实现。

但是,如果需要测试异步任务,则可以使用expectations进行测试,尽管如此,使用它的目的是为了观察没有依赖关系的单个异步代码。


我同意您的看法,它似乎更多是作为集成测试。在这种情况下,您可以利用断言getWhatever属性:

  

返回一个布尔值,该值指示当前线程是否为主线程。

答案 2 :(得分:1)

服务内部有一个电话:

DispatchQueue.main.async {
    failure(error)
}

它在测试套件中运行。因此,存在一个延迟,打破了以下规则:单元测试必须快速并且单元测试应与任何其他单元测试同时运行。

answer解释了什么是单元测试。