seanhenry / MockGenerator

An AppCode plugin to help generate Swift test doubles automatically.
GNU General Public License v3.0
71 stars 11 forks source link

Can't make it work #19

Closed pikaboo closed 6 years ago

pikaboo commented 6 years ago

Spy does not call real object

A spy is no good if it does not pass the call to the real object missing call to super.originalMethod in each generated method

seanhenry commented 6 years ago

Hi @pikaboo

At the moment all of the test doubles completely stub out the original implementation. I’m familiar of the idea for partially mocking a class and think it would be a great feature to add. I’ll look into it soon.

pikaboo commented 6 years ago

I added some code last night, but because i am not familiar with your code, and am not familiar with writing intellij plugin, i wasnt actually able to try it out, basically you need to account for a few things:

  1. does the user want a stubbed response?
  2. no parameters
  3. named parameters
  4. unnamed parameters (they begin with "_" ) before their name in the function declaration

At the moment to be able to use it i wrote those super calls myself, but as my project grows, it will be tedious task to do...

seanhenry commented 6 years ago

You should be able to try it out if you run make in the root directory. From there you can open the directory in IntelliJ and import the Maven dependencies and you can run the Plugin run configuration to try your changes.

I'm looking into adding this feature next and was thinking about generating something like this, what do you think?

class MyClass {
  func myMethod() -> Int { return 0 }
}

class MyClassSpy: MyClass {
  var invokedMyMethod = false
  var forwardToOriginalMyMethod = false // default value is false, must set to true to forward invocation
  var stubbedMyMethodResult: Int! = 0

  override func myMethod() -> Int {
    invokedMyMethod = true // always record invocations
    if forwardToOriginalMyMethod {
      return super.myMethod() // only call super if asked and ignore all stubbed values
    }
    return stubbedMyMethodResult // only act on stubbed values if not forwarding to original implementation
  }
}
pikaboo commented 6 years ago

I would prefer to call the stub only if the stub is not null I.e call the super by default, and if a stub has been set only then call the stub methods that don't return anything, may sometimes want to both call the stub and the super

I'm not able to run make, because it keeps downloading things and then claims to have failed to do so. And then says i did not set the sdk plugin, though i looked it up and i did.

seanhenry commented 6 years ago

You should be able to set the SDK by pressing cmd+; and adding an IntelliJ plugin SDK by selecting the AppCode app. If you’ve done that already then just make sure it’s named correctly. Or go to the run ‘Plugin’ configuration and select your AppCode SDK.

I can see two problems with your approach.

It won’t be possible to stub with nil and that’s perfectly valid to do in your tests.

If we keep the ‘forwardToOriginal’ Boolean only for methods without a return value then it will break all the tests if the method is given a return value. So basically, the API is not consistent between methods with return values and ones without.

What do you think?

pikaboo commented 6 years ago

forwardToOriginal is a good approach Is it possible to invoke some code during the mocked method run ? and then call the super ?

i.e

let result = stubbedMyMethodResult

if forwardToOriginal { return if needed by call super } return result

seanhenry commented 6 years ago

@pikaboo I've updated a new version with support for generating a partial spy. You need to be on AppCode 2018.2.4 or above for it to work because there were some breaking changes with AppCode's API that needed fixing. You can get the new release here or wait a day or two for JetBrains to process the new update.

You can see the final implementation of the generated code here. Hope that's useful :)