SwiftMocks

一个用于轻松模拟对象的 Swift 库。

SwiftMocks 利用 Swift 宏,让您能够轻松地创建用于测试的模拟对象。只需将 @Mock 属性添加到您的类,然后调用生成的 mock 属性即可。

mock 属性会跟踪对对象的所有调用,并允许您轻松验证对象是否使用正确的参数被调用,以及毫不费力地存根返回值。

用法

模拟

要模拟一个对象,只需将 @Mock 属性添加到您的类。 这将在您的类上生成一个 mock 属性,您可以使用它来验证对对象的调用。

// This is the class we want to mock
class MyObject {
    func doSomething() {}
}

@Mock
class MyObject {
    func doSomething() {
        mock.doSomething()
    }
    let mock = MyObjectMock() // generated
    class MyObjectMock { // generated
        var doSomethingCalls: Mock<Void, Void> = .init() // generated
        func doSomething() { // generated
            doSomethingCalls.record(()) // generated
        } // generated
    } // generated
}

存根返回值

要存根返回值,只需在 mock 属性上调用 mockCall 方法。

// This is the class we want to mock
class MyObject {
    func doSomething() -> Int { 
        mock.doSomething()
    }
}

@Mock
class MyObject {
    func doSomething() -> Int {
        mock.doSomething()
    }
}

let myObject = MyObject()
myObject.mock.doSomethingCalls.mockCall { 1 }

print(myObject.doSomething()) // this prints 1

验证调用

要验证一个方法是否被调用,只需在 mock 属性上调用 verify 方法。

// This is the class we want to mock
class MyObject {
    func doSomething() {}
}

@Mock
class MyObject {
    func doSomething(param: Int) {
        mock.doSomething(param: param)
    }
}

let myObject = MyObject()
myObject.doSomething(param: 999)

XCTAssertEqual(myObject.mock.doSomethingCalls.callCount, 1)
XCTAssertEqual(myObject.mock.doSomethingCalls.lastCall?.0, 999)

在测试中利用

在您的生产代码中,您可以像往常一样定义您的协议和类。在您的测试中,您可以将 @Mock 添加到 Mock 类,然后使用 mock 属性来验证调用。

// production code
protocol Service {
    func doSomething() -> String 
}

class RealService: Service {
    func doSomething() -> String {
        return "yes!"// production code
    }
}

let service: Service = RealService()
let useCase = UseCase(service: service)
--------------------

// test code
@Mock
class MockService: Service {
    func doSomething() -> String {
        mock.doSomething()
    }
}

func test() {
    // Given
    let mockService = MockService()
    let sut = UseCase(service: mockService)
    mockService.mock.doSomethingCalls.mockCall { "no!" }

    // When
    let result = sut.doSomething()

    // Then
    XCTAssertEqual(result, "no!")
    XCTAssertEqual(mockService.mock.doSomethingCalls.callCount, 1)
}