使用服务和插件依赖性测试自定义Grails Taglib

时间:2013-06-14 17:04:34

标签: unit-testing testing grails plugins integration-testing

我有一个自定义taglib需要调用服务方法,而service方法又使用Wslite plugin来发送和接收SOAP消息。 taglib看起来像这样。

class myTagLib {
    def myService
    def thisTag = {
        def parametersFromService = myService.method("argument")
        out << render(template:'/myFolder/myView',
        model:parametersFromService)
    }
}

我正在尝试为此taglib构建测试。我的测试类似于:

void testThisTag() {
    def appliedTagLib = applyTemplate('<thisTag attr="value" />')
    def parametersFromService = myService.method("argument")
    def renderedTemplate = render(template:'/myFolder/myView',
        model:parametersFromService)
    assertEquals appliedTagLib, renderedTemplate
}

我开始把它写成单元测试。我尝试了简单的MockFor(MyService)注释以及mocking them in a more elaborate fashion,但当taglib尝试调用它时,myService对象始终为null。

鉴于此,我决定最好将其作为集成测试;这会让我访问插件和服务,没问题。

但是,只有在测试类扩展GroovyPagesTestCase时,applyTemplate方法才有效。如果您执行,则render方法不起作用,至少不在集成测试中。我知道applyTemplate和render 在taglib的单元测试中并排工作,因为我用这种方式测试了其他taglib。

我似乎在一块岩石和一块坚硬的地方之间。要访问他们调用的服务,插件和SOAP服务,我需要进行集成测试。要使用applyTemplate()方法,我需要扩展GroovyPagesTestCase,但这会破坏render方法。我已经尝试将import grails.test.GroovyPagesTestCase添加到我的测试类中,然后从中调用applyTemplate方法,但这会导致缺少方法异常。

思想?

Grails版本是2.0.1,但如果有帮助(我们的网站处于转换状态),我可以升级到2.2.1。

--- -----编 elias建议我可以注入一个grails.gsp.PageRenderer实例来获取一个有效的渲染方法。我试过构建一个:

import org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateEngine
import grails.gsp.PageRenderer

...

def pageRenderer

...

void setUp() {
    context = grailsApplication.mainContext
    taglib = context.getBean(myTagLib.class.name)
    pageRenderer = new PageRenderer(new GroovyPagesTemplateEngine(context.getServletContext()))
}

但收到此错误:

java.lang.NullPointerException: Cannot invoke method findTemplateByPath() on null object
at grails.gsp.PageRenderer.renderViewToWriter(PageRenderer.groovy:120)
at grails.gsp.PageRenderer.render(PageRenderer.groovy:77)
at MyTagLibIntegrationTests.testThisTag(MyTagLibIntegrationTests.groovy:37)

3 个答案:

答案 0 :(得分:6)

我几天前在类似的事情上挣扎,这就是我解决它的方法:

  1. 将测试保持在集成测试中(不需要扩展任何内容)
  2. 使用grailsApplication.mainContext.getBean
  3. 抓取taglib bean的实例
  4. 使用方法调用
  5. 进行测试

    就是这样! :)

    class MyTagLibTests {
        def grailsApplication
        def taglib
    
        @Before
        void setUp(){
            // grab the taglib instance from Spring context
            taglib = grailsApplication.mainContext.getBean(MyTagLib.class.name)
        }
    
        @Test
        void myTestAboutThisTag() {
            def thisTagArgs = [:] // set up the arguments here
            assert 'shouldResultThis' == taglib.thisTag(thisTagArgs).toString()
        }
    }
    

答案 1 :(得分:1)

所以,我最终做的是扩展GroovyPagesTestCase以获取applyTemplate,然后按照elias建议注入groovyPageRenderer。 Persnickity note:你必须调用你注入的PageRenderer groovyPageRenderer,以便spring为你做所有适当的接线。所以我的测试类最终看起来像:

class myTaglibIntegrationTests extends GroovyPagesTestCase {
    PageRenderer groovyPageRenderer 
    def imageService
    @Test
    void testThisTag() {
        def appliedTagLib = applyTemplate('<thisTag attr="value" />')
        def parametersFromService = myService.method("argument")
        def renderedTemplate = groovyPageRenderer.render(template:'/myFolder/myView',
            model:parametersFromService)
        assertEquals appliedTagLib, renderedTemplate
    }
}

答案 2 :(得分:0)

更干净的解决方案将使用GroovyPageUnitTestMixin,因为它已包含渲染方法。

@grails.test.mixin.TestMixin(grails.test.mixin.GroovyPageUnitTestMixin)
class myTaglibIntegrationTests {

    def myService

    @Test
    void testThisTag() {
        def appliedTagLib = applyTemplate('<thisTag attr="value" />')
        def parametersFromService = myService.method("argument")
        def renderedTemplate = render(template:'/myFolder/myView', 
                                      model:parametersFromService)
        assertEquals appliedTagLib, renderedTemplate
    }
}

可以在这里找到关于一些简单taglib测试的好文章:http://mrhaki.blogspot.com/2013/05/grails-goodness-testing-views-and.html