4

我有一个需要调用服务方法的自定义标记库,该方法又使用Wslite 插件来发送和接收 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)注释,并以更复杂的方式模拟它们,但是myService当 taglib 试图调用它时,对象总是空的。

鉴于此,我决定最好将其简单地作为集成测试进行;这将使我可以访问插件和服务,没问题。

但是,applyTemplate 方法仅在您的测试类扩展 GroovyPagesTestCase 时才有效。但是,如果您这样做则 render 方法将不起作用,至少在集成测试中不起作用。我知道 applyTemplate 和 render在 taglib 的单元测试中确实可以一起工作,因为我已经以这种方式测试了其他 taglib。

我似乎在一块岩石和一个坚硬的地方之间。为了访问他们调用的服务、插件和 SOAP 服务,我需要一个集成测试。要使用 applyTemplate() 方法,我需要扩展 GroovyPagesTestCase,但这会破坏渲染方法。我尝试添加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)
4

3 回答 3

6

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

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

就是这样!:)

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()
    }
}
于 2013-06-14T17:12:33.543 回答
1

所以,我最终做的是扩展 GroovyPagesTestCase 以获得 applyTemplate,然后按照 elias 的建议注入 groovyPageRenderer。Persnickity 注意:您必须调用注入的 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
    }
}
于 2013-06-14T20:03:29.420 回答
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

于 2013-08-28T19:49:31.913 回答