【发布时间】:2020-08-13 23:40:24
【问题描述】:
我正在尝试对具有不同设置模式的类进行单元测试。
class Controller{
enum Mode{
case listing
case pages(String?)
}
private (set) var mode : Mode = .listing
private (set) var models = [Model]()
init() {
...
}
init(id : String) {
mode = .pages(id)
}
func fetchInfo(){
switch mode{
case .listing:
ApiManager.firstNetworkCall(){ (json, error) in ...
setupModel()
}
case .pages(let id):
ApiManager.secondNetworkCall(id : id){ (json, error) in ...
setupModel()
}
}
}
}
这两个都会用不同数量的数据更新models数组。
我现在拥有的:
var controller : Controller!
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
try super.setUpWithError()
controller = Controller()
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
controller = nil
try super.tearDownWithError()
}
func testDefaultListingMode() throws {
switch controller.mode{
case .listing:
XCTAssertTrue(true)
default:
XCTAssertFalse(false)
}
}
func testAPISetup() throws {
controller.fetchInfo()
//now what?
}
这会检查模式是否正确,但我试图更进一步,检查是否根据模式设置了正确数量的项目。并想直接从XCTestCase 调用fetchInfo() 方法并验证模型计数。
我看到的所有教程和指南都只是谈论用URLSession 伪造行为。但是 API 调用依赖于在 fetchInfo 方法中作为内部检查发生的模式,并且是唯一暴露给其他类的方法。我只是想测试该方法(以防该方法内部出现问题导致错误)。
我该怎么做呢?我不知道如何完成testAPISetup() 方法。
【问题讨论】:
-
您的控制器(及其测试)做得太多了。您的控制器的测试不应该测试任何有关 API(或它返回的内容)如何工作的内容。您应该只测试控制器是否调用了正确的 API(使用假实现)。从那里,编写单独的测试以确保 API 正常工作。
-
@Alexander-ReinstateMonica 我试图使用返回的数据量来测试是否调用了正确的 API。没有设置其他变量可以让我区分这两个响应。您是否建议仅使用
URLSession单独测试 API 而忘记“模式”?因为“你应该只测试控制器调用正确的 API”这正是我坚持的部分! -
啊,我知道是什么绊倒了你。不,不要使用结果来确定正在调用两个网络 API 中的哪一个(这在一般情况下不起作用,如果您有一个没有返回结果的依赖项怎么办?)。 Extract the interface 的网络客户端(我猜你可能很快将其称为“提取协议”),将您的网络客户端作为 VC 的依赖项注入,然后您的测试代码可以使用该协议的模拟实现,该协议检测哪个方法被调用
-
"我必须将整个 APIManager 作为参数传递。" VC 与“普通”对象有点不同,因为它们有两个阶段初始化,它们通常由系统/Storyboard 分配和最小初始化,然后从
viewDidLoad和朋友进一步“初始化”以配置您的非视图相关属性。所以你会使用类似于设置注入而不是构造函数注入的东西。您可以通过 segue 注入依赖项,或者使用默认值(您的单元测试可以覆盖) -
@Rikh 你刚刚发现了为什么对全局/静态成员的引用会使测试变得困难:)
标签: ios swift xctestcase