1

我正在尝试在动态脚手架控制器的集成测试中模拟服务。我收到一条错误消息,表明无法从测试中访问服务的控制器属性。

似乎根本无法使用单元测试来测试动态脚手架控制器,所以我正在使用集成测试。我想模拟该服务以测试我的应用程序中的错误处理。这是 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()
  }
}
4

2 回答 2

2

尝试使用 setter 方法:

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

如果你执行: println c.metaClass.methods*.name,你会看到有getSetMyService() 和getGetMyService() 之类的方法。我不确定,但可能 Grails 没有添加字段,而是添加字段获取/设置方法的 getter。

于 2013-02-10T15:24:37.610 回答
0

集成测试应按如下所示实施。如果我们在测试中模拟服务,我们必须自己重置它。Grails 不会为我们做这件事,这很神秘,因为控制器是在setUp().

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()
  }
}
于 2013-02-10T17:13:48.590 回答