Stubbing generic function responses with error
Hey,
i am trying to stub a function that takes a generic:
func createUser<T>(creds: T, completion: @escaping CreateAuthUserHandler)
The way I try to stub:
func test_registerUser_withThridParty() {
//MARK: GIVEN
weak var promise = expectation(description: "handler invoked")
let fakeToken = "XKF%$§T$FRTVDSKLRRFKVDRKFELREKLE"
let fakefacebookCreds: AuthCredential = FacebookAuthProvider.credential(withAccessToken: fakeToken)
let fake_authenticationData = AuthenticationData(userUid: "noneGiven", authCredentials: fakefacebookCreds, loginProvider: LoginServiceProvider.facebook, payloadData: ["some": 12234])
//MARK: GIVEN Mocks
stub(mock_authService) { (mock) in
mock.createUser(creds: fakefacebookCreds, completion: anyClosure()).then { (_, completion) in
completion(.success("fakeUserUid"))
}
mock.signIn(creds: fakefacebookCreds, completion: anyClosure()).then { (_, completion) in
completion(.success(()))
}
}
//MARK: WHEN
sut.executeUsecase(authenticationData: fake_authenticationData) { (error) in
if let error = error { XCTFail(error.localizedDescription) }
promise?.fulfill()
verify(self.mock_authService).createUser(creds: fakefacebookCreds, completion: anyClosure())
verify(self.mock_authService).signIn(creds: fakefacebookCreds, completion: anyClosure())
}
//MARK: THEN
waitForExpectations(timeout: 2) { (error) in
if let error = error {
XCTFail(error.localizedDescription)
}
}
}
With mock.createUser(creds: any(fakefacebookCreds.self), completion: anyClosure()) it won't compile. With the following extension the compiler does not complain when:
extension AuthCredential: Matchable {
public var matcher: ParameterMatcher<AuthCredential> {
return equal(to: self)
}
}
or usage of:
func equal(to value: AuthCredential) -> ParameterMatcher<AuthCredential> {
return ParameterMatcher { tested in
tested == value
}
}
Using any of it I receive the following error:
No stub for method
createUser(creds: T, completion: @escaping CreateAuthUserHandler)
using parameters (<FIRFacebookAuthCredential: 0x28115a8e0>, (Function)).
If i use the same function without generic parameters (and adjust the mock accordingly) i don't get an error message and the test + verify is successful, like this:
func createUser(withEmail: fakeEmail, password: fakePassword, completion: @escaping CreateAuthUserHandler)
Do I miss anything obvious? in the documentation I couldn't find anything about it
Hey, I don't see anything wrong looking at your code, it may be a bug in Cuckoo's generic functionality. It's been added recently, so we're still polishing it.
I looked into it and can't come up with a reproducer in tests. Your error message is familiar as we've fought with (Function) type that Swift gives us instead of the full closure type that we need.
Please try to fork Cuckoo and reproduce this issue with types that closely match what you're working with and when you succeed, file a PR with these findings and we'll try our best to make this error go away!
Thanks for the nice report, by the way!
For anyone in the future, instead of just liking the original issue, rather recreate minimal working example that would highlight this bug. I can't fix it if I don't know what I'm fighting.
@MatyasKriz i have sent an invitation to a private repo where i reproduce the error.
@shi-rudo That's awesome, thanks. Though for OSS it's better to fork the repo and add the bug reproducer to the tests.
@MatyasKriz here we go: https://github.com/shi-rudo/Cuckoo
I quickly added a failing test during my lunch break. I hope I did the generic mocking right, hadn't repeated it since the failed attempt.
Oh, that's cool! Thanks. I'll take a look at it.