Pergunta

I have two class:

class Foo {
    String doSomething(String a, String b) {
        return 'Not Working'
    }
}


class Bar {
    String methodIWannaTest() {
        return new Foo().doSomething('val1', 'val2')
    }
}

And I want to replace 'doSomething' in a test but it dosent work

class BarTests {
    @Test
    void testMethodIWannaTest() {
        Foo.metaClass.doSomething {String a, String b -> return 'Working'}

        assert new Bar().methodIWannaTest() == 'Working' //THIS TEST FAIL, return 'Not Working'
    }
}

*I know the test doesn't really make sens, it's just to show my point

What do I do wrong ? Is it possible to do it without using 'mockFor' ?

Foi útil?

Solução 3

I found the problem:

First, in my exemple, I forgot the '=' when defining the closure

Foo.metaClass.doSomething {String a, String b -> return 'Working'}

should be

Foo.metaClass.doSomething = {String a, String b -> return 'Working'}

While searching I also found that you cannot replace a method with optionnal parameters by a closure. Probably a bug

Outras dicas

I would suggest you to start the test afresh. Baby Steps is what I follow. :)

  • Create a new grails app.
  • Create both Foo and Bar inside src/groovy under a package.
  • Create unit test case from command prompt. Put the desired test code.
  • Execute grails test-app

[Grails v2.2.0]

Another alternative is to use Groovy MockFor.

def mock = MockFor(Foo)
mock.demand.doSomething = {String a, String b -> return 'Working'}
mock.use {
  assert new Bar().methodIWannaTest() == 'Working'
}

A downside is that there was a bug, making unit tests not clear the mock. This is fixed for 2.2.3.

I tried this on GGTS 3.2.0 and got the following results.

Copied all the code and ran on Grails 2.2.2: everything worked correctly. However, then I commented out Foo.metaClass.doSomething = {String a, String b -> return 'Working'} line and, surprisingly, the test was still passing successfully. I did more changes and the metaClass just seemed to get "cached" between tests: changes had no effect.

Then I thought if it is possible that Grails were running in interactive mode. Went to Preferences > Groovy > Grails > Grails Launch and found a checkbox 'Keep external Grails running' ticked. Its tooltip even has the following words: 'Warning: experimental feature!'. Unticking that checkbox did the trick and the metaClass no longer got cached between test runs. I am still wondering why an exprimental feature would be turned on by default...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top