XCTestCase 检查一个方法是否在结构中被调用
XCTestCase to check if a method is called within a Struct
我正在尝试测试一段代码,我在其中检查帐户是否已经创建了密钥并将其存储在钥匙串中。如果不是,它会调用启动 oauth 进程的方法。
我的第一个想法是覆盖我想在用户没有密钥的情况下调用的方法。但是我使用的是结构,因此无法继承和覆盖该方法。
如果我使用 class 我会这样:
func testInitiateOauthCalledIfSecretKeyNotFound() {
class MockKeychainAccess: KeychainAccess {
var initiateAuthorizationWasCalled: Bool = false
override initiateAuthorization() {
initiateAuthorizationWasCalled = true
}
let keychainAccess = MockKeychainAccess()
keychainAccess.authorizeWithGoogle()
XCTAssertTrue(initiateAuthorizationWasCalled)
}
我还没有测试过这段代码,所以不确定它是否可以编译。但是从逻辑上讲,它似乎可以处理我要处理的情况。如果在 authorizeWithGoogle
方法中我们调用 initiateAuthorization()
那么我就会知道那已经发生了。但是,当他们使用结构时不能这样做,因为我们不能从结构继承。
请注意:我是 TDD 的新手,所以我可能以错误的方式思考这个问题。欢迎提出其他建议。但是我不想从结构转换为 class 只是为了编写测试。我正在使用结构,因为我想变得更 swift 喜欢。
有谁知道我可以测试一个函数是否在结构中被调用的方法?
==========
编辑:
为了回应 dasdom 的回答,我添加了一个我试图实现的一般方法的示例:
override func viewDidLoad() {
setupView()
let api = DataApi()
getData(api)
}
func setupView() {
tableView.dataSource = tableViewDataSource
}
func getData(api: DataApi) {
api.getApplicationData( { (objects) in
if let applications = objects as? [Application] {
self.tableViewDataSource.setApplicationItems(applications)
self.tableView.reloadData()
}
else {
// Display error
}
})
}
所以我想注入 MockDataApi,以便它可以 return 我想要的,因为该方法采用一种 DataApi 类型。但是我不确定我应该如何创建这个 MockDataApi 结构并将它传递给这个方法。
有人可以就如何为此目的构建和使用这个模拟对象提供帮助吗?我意识到它与协议有关,但很难将其拼凑起来。
使用协议。让你的 class/struct 和你的测试模拟符合协议。注入依赖项并断言在您的模拟中调用了预期的方法。
编辑:示例
protocol DataApiProtocol {
func getApplicationData(block: [AnyObject] -> Void)
}
// Production code
struct DataApi: DataApiProtocol {
func getApplicationData(block: [AnyObject] -> Void) {
// do stuff
}
// more properties and methods
}
// Mock code
struct MockDataApi: DataApiProtocol {
var getApplicationDataGotCalled = false
func getApplicationData(block: [AnyObject] -> Void) {
getApplicationDataGotCalled = true
}
}
// Test code
func testGetData_CallsGetApplicationData() {
let sut = MyAwesomeClass()
let mockDataApi = MockDataApi()
sut.getData(mockDataApi)
XCTAssertTrue(mockDataApi.getApplicationDataGotCalled)
}
希望对您有所帮助。
我正在尝试测试一段代码,我在其中检查帐户是否已经创建了密钥并将其存储在钥匙串中。如果不是,它会调用启动 oauth 进程的方法。
我的第一个想法是覆盖我想在用户没有密钥的情况下调用的方法。但是我使用的是结构,因此无法继承和覆盖该方法。
如果我使用 class 我会这样:
func testInitiateOauthCalledIfSecretKeyNotFound() {
class MockKeychainAccess: KeychainAccess {
var initiateAuthorizationWasCalled: Bool = false
override initiateAuthorization() {
initiateAuthorizationWasCalled = true
}
let keychainAccess = MockKeychainAccess()
keychainAccess.authorizeWithGoogle()
XCTAssertTrue(initiateAuthorizationWasCalled)
}
我还没有测试过这段代码,所以不确定它是否可以编译。但是从逻辑上讲,它似乎可以处理我要处理的情况。如果在 authorizeWithGoogle
方法中我们调用 initiateAuthorization()
那么我就会知道那已经发生了。但是,当他们使用结构时不能这样做,因为我们不能从结构继承。
请注意:我是 TDD 的新手,所以我可能以错误的方式思考这个问题。欢迎提出其他建议。但是我不想从结构转换为 class 只是为了编写测试。我正在使用结构,因为我想变得更 swift 喜欢。
有谁知道我可以测试一个函数是否在结构中被调用的方法?
==========
编辑:
为了回应 dasdom 的回答,我添加了一个我试图实现的一般方法的示例:
override func viewDidLoad() {
setupView()
let api = DataApi()
getData(api)
}
func setupView() {
tableView.dataSource = tableViewDataSource
}
func getData(api: DataApi) {
api.getApplicationData( { (objects) in
if let applications = objects as? [Application] {
self.tableViewDataSource.setApplicationItems(applications)
self.tableView.reloadData()
}
else {
// Display error
}
})
}
所以我想注入 MockDataApi,以便它可以 return 我想要的,因为该方法采用一种 DataApi 类型。但是我不确定我应该如何创建这个 MockDataApi 结构并将它传递给这个方法。
有人可以就如何为此目的构建和使用这个模拟对象提供帮助吗?我意识到它与协议有关,但很难将其拼凑起来。
使用协议。让你的 class/struct 和你的测试模拟符合协议。注入依赖项并断言在您的模拟中调用了预期的方法。
编辑:示例
protocol DataApiProtocol {
func getApplicationData(block: [AnyObject] -> Void)
}
// Production code
struct DataApi: DataApiProtocol {
func getApplicationData(block: [AnyObject] -> Void) {
// do stuff
}
// more properties and methods
}
// Mock code
struct MockDataApi: DataApiProtocol {
var getApplicationDataGotCalled = false
func getApplicationData(block: [AnyObject] -> Void) {
getApplicationDataGotCalled = true
}
}
// Test code
func testGetData_CallsGetApplicationData() {
let sut = MyAwesomeClass()
let mockDataApi = MockDataApi()
sut.getData(mockDataApi)
XCTAssertTrue(mockDataApi.getApplicationDataGotCalled)
}
希望对您有所帮助。