Grails 2.2.2 Тестирование UrlMappings с исключениями

1

Возможно ли реализовать единичный тест против такого картографирования url?

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

Я попытался написать такой unit тест

@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

Если я удалю исключение: MyCustomException из UrlMapping.groovy и от модульного теста, он работает. Но я не могу этого сделать.

Теги:
unit-testing
grails

1 ответ

0

Я знаю, что прошло почти 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)
    }

}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню