seanhenry / SwiftMockGeneratorForXcode

An Xcode extension (plugin) to generate Swift test doubles automatically.
MIT License
748 stars 47 forks source link

Mystery (to me!) Void parameter #35

Closed iandundas closed 4 years ago

iandundas commented 4 years ago

When generating a spy with a function which has a closure, there's always an extra Void parameter

protocol SimpleExampleProtocol {
    func someFunction(callback: (Bool) -> (String))
}

class SimpleExampleMock: SimpleExampleProtocol {
    var invokedSomeFunction = false
    var invokedSomeFunctionCount = 0
    var stubbedSomeFunctionCallbackResult: (Bool, Void)? // <--- here 
    func someFunction(callback: (Bool) -> (String)) {
        invokedSomeFunction = true
        invokedSomeFunctionCount += 1
        if let result = stubbedSomeFunctionCallbackResult {
            _ = callback(result.0)
        }
    }
}

so when setting up spies, we have to use a tuple always with an extra () at the end:

spy.stubbedSomeFunctionCallbackResult = (Bool, ())

Is this intentional behaviour? Instinctively it felt like spy.stubbedSomeFunctionCallbackResult = true would be better, but possibly this is a misunderstanding.

Thanks!

seanhenry commented 4 years ago

Hi @iandundas

Thanks for raising this issue. The reason for this is so you can choose not to call the closure. It doesn't make sense for your example but consider your example with an optional closure parameter:

var stubbedSomeFunctionCallbackResult: Bool? // <--- The closure is always called because nil is allowed
var stubbedSomeFunctionCallbackResult: (Bool?, Void)? // <--- If this is nil, the closure isn't called. But it can still be called with nil
func someFunction(callback: (Bool?) {
}

Does that make sense?

iandundas commented 4 years ago

I think I understand now :) thanks for the response!