如何在动态支架Grails控制器的集成测试中模拟服务?

时间:2013-02-10 13:31:03

标签: unit-testing grails mocking

我正在尝试在动态支架控制器的集成测试中模拟服务。我收到一个错误,指示无法从测试中访问该服务的控制器属性。

似乎动态支架控制器根本无法使用单元测试进行测试,所以我正在使用集成测试。我想模拟服务来测试我的应用程序中的错误处理。这是Grails 2.2.0中的错误还是我做错了?

grails test-app的结果是:

groovy.lang.MissingPropertyException: No such property: myService for class: MyController

示例:

我修改了src/templates/scaffolding/Controller.groovy

class ${className}Controller {
  MyService myService

  def action() {
    render myService.serviceMethod()
  }
}

动态搭建MyController.groovy

class MyController {
    static scaffold = MyDomainClass
}

整合测试MyControllerTests.groovy

class MyControllerTests extends GroovyTestCase {
  def myController

  @Before
  void setUp() {
    myController = new MyController()
  }

  void testMock() {
    myController.myService = [ serviceMethod : { return "foo" } ] as MyService
    controller.action()
  }
}

2 个答案:

答案 0 :(得分:2)

尝试使用setter方法:

void testMock() {
    myController.setMyService([ serviceMethod : { return "foo" } ])
    controller.action()
}

如果执行:println c.metaClass.methods*.name,您将看到有getSetMyService()和getGetMyService()等方法。我不确定,但Grails可能不会添加字段,而是使用get get / set方法获取字段。

答案 1 :(得分:0)

集成测试应如下所示实现。如果我们在测试中模拟服务,我们必须自己重置它。由于控制器是在setUp()中创建的,所以Grails不会为我们这样做,因为它是神秘的。

droggo上面的回答揭示了在SUT中注入模拟的正确方法。我还将添加一个使用Groovy模拟的示例。但它有点冗长。

class MyControllerTests extends GroovyTestCase {
  def myController
  def myService

  @Before
  void setUp() {
    myController = new MyController()
  }

  @After
  void tearDown() {
    myController.setMyService(myService)
  }

  void testMapMock() {
    myController.setMyService([ serviceMethod : { return "foo" } ] as MyService)
    controller.action()
  }

  void testGroovyMock() {
    def myServiceMockContext = new StubFor(MyService)
    myServiceMockContext.demand.serviceMethod() { -> return "bar" }
    def myService = myServiceMockContext.proxyInstance()
    controller.setMyService(myService)
    controller.action()
  }
}