2013-02-10 20 views
1

我试图在动态脚手架控制器的集成测试中模拟服务。我收到一个错误,指出服务的控制器属性不能从测试中访问。如何在动态脚手架Grails控制器的集成测试中模拟服务?

似乎动态脚手架的控制器不能用单元测试进行测试,所以我正在使用集成测试。我想嘲笑服务来测试我的应用程序中的错误处理。这是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

尝试使用setter方法:

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

如果执行:println c.metaClass.methods*.name,你会看到有像getSetMyService()和getGetMyService()方法。我不确定它,但可能Grails不添加字段,而是get字段get/set方法的getters。

+0

谢谢! controller.setXxxService()方法取得了诀窍!不过,作为参数的Map需要一个类型转换:'controller.setMyService([...]作为MyService)'。此外,您需要将服务重置为真正的服务以进行下一个测试。 Grails在设置好之后似乎会保持模拟。我将在下面的另一个答案中显示一个示例实现。 – apa64 2013-02-10 17:03:05

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() 
    } 
} 
相关问题