【问题标题】:Grails 2.2.2 UrlMappings testing with exceptionsGrails 2.2.2 UrlMappings 测试异常
【发布时间】:2015-02-05 15:48:21
【问题描述】:

是否可以针对此类 url 映射实施单元测试?

"500" (controller: 'error', action: 'handle', exception: MyCustomException)

我试过写这样的单元测试

@TestFor(UrlMappings)
@Mock(ErrorController)
class UrlMappingsTest {

    void test() {
        assertForwardUrlMapping(500, controller: "error", action: "handle", exception: MyCustomException)


    }

}

但得到junit.framework.AssertionFailedError: url '500' did not match any mappings

如果我从 UrlMapping.groovy 和单元测试中删除异常:MyCustomException,它就可以工作。但我做不到。

【问题讨论】:

    标签: java unit-testing grails


    【解决方案1】:

    我知道已经快 2 年了,但我昨天也遇到了这个问题,虽然使用的是 Grails 2.4.4,所以我会在这里发布一个解决方案,以防有人碰到这个问题。

    好像写测试还不够,写测试比写实际代码要多 1000% 的时间更令人不安! :)

    无论如何,问题是UrlMappingsUnitTestMixin 无法处理这种情况。

    这里报告了一个官方错误: https://github.com/grails/grails-core/issues/10226 并在上个月推出了一个修复程序。

    如果您想利用 Grails 2.4.4 中的修复,您可以创建一个 mixin UrlMappingsUnitTestMixinBugFix,然后在 UrlMappingsTest 中使用它。

    UrlMappingsUnitTestMixin.groovy

    package com.example.util.test
    
    import grails.util.Holders
    import junit.framework.AssertionFailedError
    import org.codehaus.groovy.grails.commons.ControllerArtefactHandler
    import org.codehaus.groovy.grails.commons.GrailsControllerClass
    import org.codehaus.groovy.grails.web.mapping.UrlMappingsHolder
    
    import static junit.framework.Assert.assertEquals
    
    /**
     * Methods below are copied from {@link grails.test.mixin.web.UrlMappingsUnitTestMixin}
     *
     * <p>This method is here because the {@link grails.test.mixin.web.UrlMappingsUnitTestMixin} in Grails 2.4.4 has a bug and this code fixes it.
     * <p>Link to the bug: <a href="https://github.com/grails/grails-core/issues/10226">here</a>.
     *
     * <p>To use this class just write UrlMappingsTest as per Grails guidelines and add a static code block to the Test:
     * <p>
     * <code>
     *  static {
     *      UrlMappingsTest.mixin(UrlMappingsUnitTestMixinBugFix)
     *  }
     * </code>
     */
    class UrlMappingsUnitTestMixinBugFix {
    
        void assertForwardUrlMapping(assertions, url) {
            assertForwardUrlMapping(assertions, url, null)
        }
    
        void assertForwardUrlMapping(assertions, url, paramAssertions) {
    
            def assertionKeys = ["controller", "action", "view"]
            final String KEY_EXCEPTION = 'exception'
    
            UrlMappingsHolder mappingsHolder = Holders.applicationContext.getBean("grailsUrlMappingsHolder", UrlMappingsHolder)
            if (assertions.action && !assertions.controller) {
                throw new AssertionFailedError("Cannot assert action for url mapping without asserting controller")
            }
    
            if (assertions.controller) assertController(assertions.controller, url)
            if (assertions.action) assertAction(assertions.controller, assertions.action, url)
            if (assertions.view) assertView(assertions.controller, assertions.view, url)
    
            def mappingInfos
            if (url instanceof Integer) {
                mappingInfos = []
    
                // -------- START FIX --------
    
                // -------- OLD CODE (below) --------
                // def mapping = mappingsHolder.matchStatusCode(url)
                // if (mapping) mappingInfos << mapping
    
                // -------- FIXED CODE (below) --------
                def mapping
                if (assertions."$KEY_EXCEPTION") {
                    mapping = mappingsHolder.matchStatusCode(url, assertions."$KEY_EXCEPTION" as Throwable)
                } else {
                    mapping = mappingsHolder.matchStatusCode(url)
                }
                if (mapping) mappingInfos << mapping
    
                // -------- END FIX --------
    
            } else {
                mappingInfos = mappingsHolder.matchAll(url)
            }
    
            if (mappingInfos.size() == 0) throw new AssertionFailedError("url '$url' did not match any mappings")
    
            def mappingMatched = mappingInfos.any { mapping ->
                mapping.configure(webRequest)
                for (key in assertionKeys) {
                    if (assertions.containsKey(key)) {
                        def expected = assertions[key]
                        def actual = mapping."${key}Name"
    
                        switch (key) {
                            case "controller":
                                if (actual && !getControllerClass(actual)) return false
                                break
                            case "view":
                                if (actual[0] == "/") actual = actual.substring(1)
                                if (expected[0] == "/") expected = expected.substring(1)
                                break
                            case "action":
                                if (key == "action" && actual == null) {
                                    final controllerClass = getControllerClass(assertions.controller)
                                    actual = controllerClass?.defaultAction
                                }
                                break
                        }
    
                        assertEquals("Url mapping $key assertion for '$url' failed", expected, actual)
                    }
                }
                if (paramAssertions) {
                    def params = [:]
                    paramAssertions.delegate = params
                    paramAssertions.resolveStrategy = Closure.DELEGATE_ONLY
                    paramAssertions.call()
                    params.each { name, value ->
                        assertEquals("Url mapping '$name' parameter assertion for '$url' failed", value, mapping.params[name])
                    }
                }
                return true
            }
    
            if (!mappingMatched) throw new IllegalArgumentException("url '$url' did not match any mappings")
        }
    
        private GrailsControllerClass getControllerClass(controller) {
            return grailsApplication.getArtefactByLogicalPropertyName(ControllerArtefactHandler.TYPE, controller)
        }
    
    }
    

    UrlMappingsTest.groovy

    import com.example.controller.ErrorController
    import com.example.util.test.UrlMappingsUnitTestMixinBugFix
    import grails.test.mixin.Mock
    import grails.test.mixin.TestFor
    
    @TestFor(UrlMappings)
    @Mock(ErrorController)
    class UrlMappingsTest {
    
    
    static {
        UrlMappingsTest.mixin(UrlMappingsUnitTestMixinBugFix)
    }
    
    
    void test() {
    
            assertForwardUrlMapping(500, controller: "error", action: "handle", exception: MyCustomException)
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      相关资源
      最近更新 更多