Unit testing 使用服务和插件依赖项测试定制Grails标记库

Unit testing 使用服务和插件依赖项测试定制Grails标记库,unit-testing,testing,grails,plugins,integration-testing,Unit Testing,Testing,Grails,Plugins,Integration Testing,我有一个自定义标记库,需要调用服务方法,服务方法反过来使用发送和接收SOAP消息。taglib看起来像这样 class myTagLib { def myService def thisTag = { def parametersFromService = myService.method("argument") out << render(template:'/myFolder/myView', model:param

我有一个自定义标记库,需要调用服务方法,服务方法反过来使用发送和接收SOAP消息。taglib看起来像这样

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

但是收到这个错误:

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)

前几天我也在为类似的事情挣扎,下面是我如何解决的:

  • 将测试保持为集成测试(不需要扩展任何内容)
  • 使用
    grailsApplication.mainContext.getBean
  • 使用方法调用测试它
  • 就这样!:)


    因此,我最终做的是扩展GroovyPagestCase以获得applyTemplate,然后按照elias的建议注入GroovyPagestEnder。挑剔的注意:为了让spring为您完成所有适当的布线,您必须调用注入的PageRenderer groovyPageRenderer。所以我的测试课最终看起来像:

    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
        }
    }
    
    类myTaglibIntegrationTests扩展了GroovyPagesTestCase{
    页面渲染器GroovyPagerEnder
    def图像服务
    @试验
    void testThisTag(){
    def appliedTagLib=applyTemplate(“”)
    def参数sfromservice=myService.method(“参数”)
    def renderedTemplate=groovyPageRenderer.render(模板:'/myFolder/myView',
    型号:参数(来自服务)
    assertEquals appliedTagLib,renderedTemplate
    }
    }
    
    更干净的解决方案将使用GroovyPageUnitTestMixin,因为它已经包含一个render方法

    @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
        }
    }
    
    @grails.test.mixin.TestMixin(grails.test.mixin.GroovyPageUnitTestMixin)
    类myTaglibIntegrationTests{
    def myService
    @试验
    void testThisTag(){
    def appliedTagLib=applyTemplate(“”)
    def参数sfromservice=myService.method(“参数”)
    def renderedTemplate=render(模板:'/myFolder/myView',
    型号:参数(来自服务)
    assertEquals appliedTagLib,renderedTemplate
    }
    }
    

    关于一些简单的taglib测试的一篇好文章可以在这里找到:

    这很有帮助,但是手动定义要比较的字符串让我像老猛犸一样伤心。我要看看我是否能找到一些方法使渲染方法可用,这样我就可以与之进行比较。对!我认为您可以在测试中插入一个
    groovyPageRenderer
    的实例,并尝试使用它的render方法……但是如果我可以做到这一点,为什么不扩展GroovyPagesTestCase并将applyTemplate()的输出与render()的输出进行比较呢?请参阅我在尝试注入页面渲染器时的编辑。这可能是我在正确执行基本依赖项注入方面的一个失败。好吧,我认为你可以这样做,但它仍然只适用于只呈现模板的taglib。我将我的方法作为taglibs集成测试的一个更通用的解决方案,它非常有用,特别是GroovyPagerender的评论,它让我走上了正确的道路。由于这个问题的目的是将taglib的输出与呈现的模板进行比较,因此我不能完全接受它作为答案,但我将尝试在值得信任的地方给予信任。:)您不需要在安装程序中对其进行初始化,只需为实例使用正确的bean名称,
    def groovyPageRenderer
    ,它就应该这样做。请参阅elias的回答,了解另一个有用的想法,即为taglib编写一个测试,该测试在其他情况下可能会更好地工作:
    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)
    
    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()
        }
    }
    
    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
        }
    }
    
    @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
        }
    }