Brightify / Cuckoo

Boilerplate-free mocking framework for Swift!
MIT License
1.67k stars 174 forks source link

Cannot mock protocol that conforms to ObservableObject #381

Closed SumoSimo closed 6 months ago

SumoSimo commented 3 years ago

Hi there. I'm running into an issue with the inability to mock protocols that conform to ObservableObject. Consider the following protocol:

protocol TestProtocol: ObservableObject {}

The generated mock and stub for this protocol is as follows:

class MockTestProtocol: TestProtocol, Cuckoo.ProtocolMock {

     typealias MocksType = TestProtocol

     typealias Stubbing = __StubbingProxy_TestProtocol
     typealias Verification = __VerificationProxy_TestProtocol

     let cuckoo_manager = Cuckoo.MockManager.preconfiguredManager ?? Cuckoo.MockManager(hasParent: false)

    private var __defaultImplStub: TestProtocol?

     func enableDefaultImplementation(_ stub: TestProtocol) {
        __defaultImplStub = stub
        cuckoo_manager.enableDefaultStubImplementation()
    }

     struct __StubbingProxy_TestProtocol: Cuckoo.StubbingProxy {
        private let cuckoo_manager: Cuckoo.MockManager

         init(manager: Cuckoo.MockManager) {
            self.cuckoo_manager = manager
        }

    }

     struct __VerificationProxy_TestProtocol: Cuckoo.VerificationProxy {
        private let cuckoo_manager: Cuckoo.MockManager
        private let callMatcher: Cuckoo.CallMatcher
        private let sourceLocation: Cuckoo.SourceLocation

         init(manager: Cuckoo.MockManager, callMatcher: Cuckoo.CallMatcher, sourceLocation: Cuckoo.SourceLocation) {
            self.cuckoo_manager = manager
            self.callMatcher = callMatcher
            self.sourceLocation = sourceLocation
        }

    }
}
class TestProtocolStub: TestProtocol {

}

Below is a screenshot of the errors for __defaultImplStub and func enableDefaultImplementation(_ stub: TestProtocol) { ... }:

MockTestProtocol error

I was able to resolve the compilation errors by assigning the MocksType typealias to TestProtocolStub, setting the type for __defaultImplStub to TestProtocolStub, and setting the parameter type of enableDefaultImplementation(_ stub: TestProtocol) to TestProtocolStub. I don't know if this is the exact solution because I don't understand the underpinnings and nuances of the Cuckoo framework, but it can serve as a lead.

If this turns out to be the solution, then I suppose the Cuckoo framework should be updated to account for protocols that conform to protocols that have Self or associated type requirements by using the approach aforementioned. If this issue can be solved, it would also take care of #364. The difference between this issue and #364 is that I cannot exclude protocols that conform to ObservableObject.

Any help is greatly appreciated since testing in the context of SwiftUI is picking up. Thank you!

MatyasKriz commented 6 months ago

I'm not sure if it's the correct way to solve this, but I've added the any keyword in the generated mocks to all protocols and the tests pass with flying colors, so we'll try it and see if the real world has a problem with it. 😁