如何创建带有闭包的单元测试用例



我已经在我的应用程序中创建了单元测试用例,到目前为止还不错。我在我的项目中使用MVVM;我有API请求,该请求具有success & failureclosures。我如何为它制作测试用例。

我尝试过的:

var mockAPIService: MockApiService!
override func setUp() {
super.setUp()
mockAPIService = MockApiService()
sut = PhotoListViewModel(apiService: mockAPIService)
}
func test_fetch_photo() {
sut.apiSuccessClouser = { dataValue in
print("apiSuccessClouser") // This doesnot executes 
XCTAssert(dataValue)
}
}

但是print("apiSuccessClouser")没有执行。。我只是想让clouser与单元测试一起工作。

将dataValue存储在某个变量中,并使用期望值等待闭包执行,然后进行测试。注:此示例是用swift 4 编写的

let yourExpectationName = expectation(description: "xyz")
var dataToAssert = [String]() //replace with you data type
sut.apiSuccessClouser = { dataValue in
dataToAssert = dataValue
yourExpectationName.fulfill()
}

waitForExpectations(timeout: 3) { (error) in //specify wait time in seconds
XCTAssert(dataToAssert)
}
MockApiService中的apiSuccessClouser是闭包(()->Void?)?类型的属性。

sut.apiSuccessClouser = { ... }行中,您为属性apiSuccessClouser分配了一个闭包,但您从未访问过这个闭包,因此要执行print("apiSuccessClouser")

要执行打印("apiSuccessClouser"(,您需要调用闭包

sut.apiSuccessClouser?()

所以重构测试,比如:

func test_fetch_photo() {
sut.apiSuccessClouser = { dataValue in
print("apiSuccessClouser") // This doesnot executes 
XCTAssert(dataValue)
}
sut.apiSuccessClouser?()
}

了解更多信息:https://docs.swift.org/swift-book/LanguageGuide/Closures.html

要用普通XCTest测试这种异步代码,需要使用XCTestExpectation

func test_fetch_photo() {
let expectation = XCTestExpectation(description: "photo is fetched")
sut.apiSuccessClouser = { dataValue in
// I like to run the assertions directly inside of the async closure, that way
// you don't need to have vars around to store the value in order to check it
// afterwards
XCTAssert(dataValue)
expectation.fulfill()
}
sut.apiSuccessClouser?()
// The timeout duration depends on what kind of async work the closure is doing,
// here, because it's called directly, you probably don't need long.
wait(for: [expectation], timeout: 0.1)
}

断言库Nimble还提供了一种测试异步代码的巧妙方法。

func test_fetch_photo() {
waitUntil { done in
self.sut.apiSuccessClouser = { dataValue in
assert(dataValue).toNot(beNil())
done()
}
self.sut.apiSuccessClouser?()
}
}

除了waitUntil,Nimble还有一个.toEventually断言。

你也问过使用Quick。Quick是一个测试工具库,它允许您以不同的方式编写测试,但它不会改变您编写实际期望的方式。

describe("Name of your system under test") {
it("does something asynchronously") {
let sut = ...

waitUntil { done in
self.sut.apiSuccessClouser = { dataValue in
assert(dataValue).toNot(beNil())
done()
}
self.sut.apiSuccessClouser?()
}
}
}

最新更新