问题是编写一个断言当前线程是主线程的单元测试有意义吗? 优点/缺点?
最近,我看到了单元测试,该单元测试为服务的回调声明了当前线程。我不确定这是个好主意,我相信这是一种更多的集成测试。我认为,单元测试应该孤立地声明方法,并且不应该了解服务使用者的性质。
在iOS中,此服务的使用者旨在成为一个UI,默认情况下,它具有在主线程上运行代码的约束。
更新:
服务内部有一个电话:
DispatchQueue.main.async {
failure(error)
}
它在测试套件中运行,并且没有被模拟。因此,有一个 delay 违反了以下规则:单元测试必须快速并且单元测试应与任何其他单元测试同时运行。
答案 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解释了什么是单元测试。