Brightify / Cuckoo

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

Unable to mock a class with immutable properties that implements a protocol #396

Closed pradnya-nikam closed 5 months ago

pradnya-nikam commented 3 years ago

Hello! Cuckoo works well to create mocks for some of my simpler classes, but it is not working for models that have a pretty complicated hierarchy - appreciate if someone can help me get around this problem!

For classes that implement a protocol, cuckoo tries to override read only properties in generated mocks which doesn't compile. Best to explain with an example.

eg


protocol DemoProtocol {
  var id: String { get }
}

class Demo: DemoProtocol {
  let id: String
  let name: String
  init(id: String, name: String) {
    self.id = id
    self.name = name
  }
}

Since the protocol needs to declare id as a var (Swift protocols cannot require properties to be immutable), Cuckoo tries to override id, which of course doesn't compile.

Generated mocks for this file:


class MockDemo: Demo, Cuckoo.ClassMock {

     typealias MocksType = Demo

     typealias Stubbing = __StubbingProxy_Demo
     typealias Verification = __VerificationProxy_Demo

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

    private var __defaultImplStub: Demo?

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

     override var id: String {   //⚠️ Compile error: Cannot override immutable 'let' property 'id' with the getter of a 'var'
        get {
            return cuckoo_manager.getter("id",
                superclassCall:

                    super.id
                    ,
                defaultCall: __defaultImplStub!.id)
        }

    }

Compiler error:

Error: Cannot override immutable 'let' property 'id' with the getter of a 'var'

Any advice on how to get around this?

MatyasKriz commented 3 years ago

Hey, @pradnya-nikam. That's a good point, though I'm not really sure how to solve this. @TadeasKriz do you have an idea if that's possible?

aronbudinszky commented 5 months ago

I know it's not really a satisfying workaround, but anyone stumbling into this issue:

[modules.YourModule.options]
protocolsOnly = true

Protocols will not be affected by this issue. Of course it forces you to always use protocols for mocks. This may or may not be acceptable.

MatyasKriz commented 5 months ago

@aronbudinszky does this issue still apply in Cuckoo 2.0? If the only way to get this working is simply ignoring the constants, it shouldn't be hard to implement.

MatyasKriz commented 5 months ago

I just tested this and it does.

I think I've managed to fix this, could I ask you, @aronbudinszky, to try version 2.0.5 if it works for you even without the protocolsOnly option?