grailsmockinggmock

Mock testing in Grails 2.0 errors


I've recently upgraded a Grails 1.3.7 project up to Grails 2.0.4 and noticed that many of my unit tests with mocking have started to fail. The Controller tests seem to pass just fine, the issue comes when you have Services collaborating with one another and try to mock out the calls to the collaborators. The strange part about it is if I run the single test, it passes, but as soon as I run the entire suite, they fail giving the error:

No more calls to 'getName' expected at this point. End of demands.
junit.framework.AssertionFailedError: No more calls to 'getName' expected at this point. End of demands.

I've even tried using GMock instead of new MockFor(), but get this very similar error:

No more calls to 'getSimpleName' expected at this point. End of demands.
junit.framework.AssertionFailedError: No more calls to 'getSimpleName' expected at this point. End of demands.

Here's a contrived example showing how to duplicate the errors I'm getting, and the entire sample project on GitHub at https://github.com/punkisdead/FunWithMocks. Any ideas of how to make this work?

BarController:

package funwithmocks

class BarController {

  def barService
  def fooService

  def index() { }
}

BarService:

package funwithmocks

class BarService {

  def fooService
  def bazService

  def serviceMethod() {

  }
}

BarControllerTests:

package funwithmocks

import grails.test.mixin.*
import org.junit.*
import groovy.mock.interceptor.MockFor

/**
 * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
 */
@TestFor(BarController)
class BarControllerTests {

  def fooService
  def barService

  @Before
  public void setUp() {
    fooService = new MockFor(FooService)
    fooService.use {
      controller.fooService = new FooService()
    }

    barService = new MockFor(BarService)
    barService.use {
      controller.barService = new BarService()
    }
  }

  @Test
  void doSomething() {
    controller.index()
  }
}

BarServiceTests: package funwithmocks

import grails.test.mixin.*
import org.junit.*
import groovy.mock.interceptor.MockFor

/**
 * See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions
 */
@TestFor(BarService)
class BarServiceTests {

  def fooService
  def bazService

  @Before
  public void setUp() {
    fooService = new MockFor(FooService)
    fooService.use {
      service.fooService = new FooService()
    }

    bazService = new MockFor(BazService)
    bazService.use {
      service.bazService = new BazService()
    }
  }

  @Test
  void callSomeService() {
    service.serviceMethod()
  }
}

Solution

  • You shouldn't to combine the new test mixin with MockFor groovy class. Replace all MockFor instance with the mockFor method.

    http://grails.org/doc/latest/guide/testing.html#mockingCollaborators