Java Grails2.2.2 UrlMappings异常测试

Java Grails2.2.2 UrlMappings异常测试,java,unit-testing,grails,Java,Unit Testing,Grails,是否可以针对这样的url映射实现单元测试 "500" (controller: 'error', action: 'handle', exception: MyCustomException) 我试着编写这样的单元测试 @TestFor(UrlMappings) @Mock(ErrorController) class UrlMappingsTest { void test() { assertForwardUrlMapping(500, controller: "e

是否可以针对这样的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”不匹配任何映射


如果我从UrlMapping.groovy和单元测试中删除exception:MyCustomException,它就会工作。但是我做不到。

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

如果仅仅编写测试是不够的,那么编写测试所花费的时间比编写实际代码所花费的时间还要多1000%,这就更令人不安了

无论如何,问题是URLMappingSunitestMixin不能处理这种情况

这里报告了一个官方错误: 上个月刚刚推出了一个修复方案

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

urlmappingsunitestmixin.groovy UrlMappingsTest.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)
    }

}
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)
    }

}