I'm trying to mock a service with cuckoo in swift. Here's the original function in the service:
typealias GetAppConfigCompletionHandler = (_ response: AppConfig) -> Void
func getAppConfig(delegate: ErrorCoordinatorDelegate,
retryClosure: (() -> Void)?,
response responseCallback: @escaping GetAppConfigCompletionHandler) {
guard let appConfigUrl = "some/url"
HttpClientService<AppConfig>.makeRequest(errorCoordinatorDelegate: delegate,
retryClosure: retryClosure,
url: appConfigUrl) { appConfig in
responseCallback(appConfig)
}
}
Then in the tests I'm trying to mock the EndPointService to make it call back my mocked value instead of calling an API:
guard let mockedAppConfig: AppConfig = JsonTestingHelper.decodeJSON(resourceName: "mockAppConfig",
model: AppConfig.self) else {
fail("failed to create mockAppConfig from JSON")
return
}
stub(endPointServiceMock) { mock in
when(mock.getAppConfig(delegate: any(),
retryClosure: any(),
response: any())).then { callback in
callback(mockedAppConfig) //error is here
}
}
And this is how the generated mock function looks like:
func getAppConfig(delegate: ErrorCoordinatorDelegate, retryClosure: (() -> Void)?, response responseCallback: @escaping GetAppConfigCompletionHandler) {
return cuckoo_manager.call("getAppConfig(delegate: ErrorCoordinatorDelegate, retryClosure: (() -> Void)?, response: @escaping GetAppConfigCompletionHandler)",
parameters: (delegate, retryClosure, responseCallback),
escapingParameters: (delegate, retryClosure, responseCallback),
superclassCall:
Cuckoo.MockManager.crashOnProtocolSuperclassCall()
,
defaultCall: __defaultImplStub!.getAppConfig(delegate: delegate, retryClosure: retryClosure, response: responseCallback))
}
From what it looks like it should work, however I get compiler complaining at the callback(mockedAppConfig) line:
Cannot call value of non-function type '(ErrorCoordinatorDelegate, (() -> Void)?, MockEndPointServiceType.GetAppConfigCompletionHandler)' (aka '(ErrorCoordinatorDelegate, Optional<(() -> ())>, (AppConfig) -> ())')
What am I missing?
The error message, while a bit complex, tells you exactly what the issue is;
When you're calling callback(mockedAppConfig)
, your callback
variable is actually a tuple with 3 parameters (a ErrorCoordinatorDelegate
, an optional Void
function, and a function that takes in a AppConfig
parameter).
In order to fix this error, all you need to do is:
callback.2(mockedAppConfig)
(This is how you reference any unnamed parameter of a tuple)
Or, better yet, you could make your stub look like this:
stub(endPointServiceMock) { mock in
when(mock.getAppConfig(delegate: any(),
retryClosure: any(),
response: any())).then { _, _, callback in
callback(mockedAppConfig)
}
}
Which is a bit more standard and less obscure :)