seanhenry / SwiftMockGeneratorForXcode

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

Doesn't generate static methods #33

Closed BergQuester closed 4 years ago

BergQuester commented 4 years ago

Create a protocol with a static method:

protocol TestProtcol {
    static func staticMethod()
}

And start a mock:

class Mock: TestProtcol {

}

Then generate a spy.

The static method will not be generated. I have a class that I can swap out for my tests, so generating mock static methods would be very useful.

seanhenry commented 4 years ago

Hi @BergQuester

Thanks for raising this issue. Static mocks are a little more complicated because it will be very easy to accidentally keep state between tests. And I think, no matter what we do, static methods cannot be mocked when doing parallel testing.

That said, I can see how the missing support for static methods is irritating since they won't compile and require code to be added manually after each generation. So perhaps with documentation of their restrictions we can add this feature.

I think the main challenge is to easily reset mock state between tests so I've come up with the following:

protocol MyProtocol {
    static func a()
}

class MyProtocolMock: MyProtocol {

    class Static {
        var invokedA = false
        var invokedACount = 0
    }

    static var `static` = Static()

    static func a() {
        MyProtocolMock.static.invokedA = true
        MyProtocolMock.static.invokedACount += 1
    }
}

class MyClass {
    static func a() {} // cannot be overridden
    class func b() {}
}

class MyClassMock: MyClass {

    class Static {
        var invokedB = false
        var invokedBCount = 0
    }

    static var `static` = Static()

    override class func b() {
        MyClassMock.static.invokedB = true
        MyClassMock.static.invokedBCount += 1
    }
}

class MyTest: XCTestCase {

    var mock: MyProtocolMock!

    override func setUp() {
        super.setUp()
        mock = MyProtocolMock()
        MyProtocolMock.static = .init()
    }
}

What do you think?

seanhenry commented 4 years ago

Closed due to inactivity