Search code examples
swiftmockingxctest

Why can't MockingBird find my stub with a type argument?


I'm using MockingBird for mocks in a Swift 5 project. A test like this passes fine:

// In app
protocol SomeProtocol {
    func getNumber() -> Int
}

// In tests
import Mockingbird
import XCTest
@testable import MyApp

class Test: XCTestCase {
    func testExample() throws {
        let mock: SomeProtocolMock! = mock(SomeProtocol.self)
        given(mock.getNumber()).willReturn(1)
        _ = mock.getNumber() as Int
    }
}

However, if I add a type argument, it doesn't work:

// In app
protocol SomeProtocol {
    func getNumber<T>(_ type: T.Type) -> Int
}

// In tests
import Mockingbird
import XCTest
@testable import MyApp

class Test: XCTestCase {
    func testExample() throws {
        let mock: SomeProtocolMock! = mock(SomeProtocol.self)
        given(mock.getNumber(Int.self)).willReturn(1)
        _ = mock.getNumber(Int.self) as Int
    }
}

Running the latter test gives the following error:

Missing stubbed implementation for 'getNumber(_ type: T.Type) -> Int' with arguments [Int (by reference)]

Make sure the method has a concrete stub or a default value provider registered with the return type.

Examples:
given(someMock.getNumber(…)).willReturn(someValue)
given(someMock.getNumber(…)).will { return someValue }
someMock.useDefaultValues(from: .standardProvider)

Why doesn't this work? Is there any way I can get around this, e.g. using any()?


Solution

  • I think I know the problem.

    Change the parameter to any() as Int.Type.

    The test file would look like this:

    // In tests
    import Mockingbird
    import XCTest
    @testable import MyApp
    
    class Test: XCTestCase {
        func testExample() throws {
            let mock: SomeProtocolMock! = mock(SomeProtocol.self)
            given(mock.getNumber(any(Int.Type.self))).willReturn(1)
            _ = mock.getNumber(Int.self) as Int
        }
    }