Использование FiltersUnitTestCase для модульного тестирования фильтров безопасности Shiro, IllegalStateException - PullRequest
4 голосов
/ 25 сентября 2011

Обновление : я изменил этот вопрос, чтобы описать конкретную проблему, с которой я столкнулся.Это связано с тем, что модульное тестирование фильтров будет поддерживаться в Grails 2.0, поэтому, надеюсь, документация будет лучше.

Я пытаюсь написать модульные тесты для фильтров, которые я настроил для реализации безопасности Shiro в моем приложении grails.Я использую Grails 1.3.7 и не смогу некоторое время использовать 2.0 (если вообще когда-либо) для этого конкретного проекта.

Идея моего фильтра заключается в том, что мне нужно предоставить анонимный доступ к номеру или контроллеру/ комбинации действий, но защищают доступ к другим.Я также хочу, чтобы он был отказоустойчивым, т. Е. Если вы забудете явно разрешить доступ, то доступ будет запрещен.

Класс фильтра

class SecurityFilters {
    def filters = {

        homeAccess(controller: "home", action: "*") {
            before = {

                // Allow all access
                request.accessAllowed = true
            }
        }

        serverAccess(controller: "server", action: "list") {
            before = {

                // Allow all access
                request.accessAllowed = true
            }
        }

        layerAccess(controller: "layer", action: "list|listBaseLayersAsJson|listNonBaseLayerAsJson|showLayerByItsId") {
            before = {

                // Allow all access
                request.accessAllowed = true
            }
        }

        all(uri: "/**") {
            before = {

                // Check if request has been allowed by another filter
                if (request.accessAllowed) return true            

                // Ignore direct views (e.g. the default main index page).
                if (!controllerName) return true

                // Access control by convention.
                accessControl(auth: false)
            }
        }
    }
}

Модульtests

import org.codehaus.groovy.grails.plugins.web.filters.FilterConfig

class SecurityFiltersTests extends FiltersUnitTestCase {

    protected void setUp() {
        super.setUp()
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testHomeControllerFilter() {

        checkFilter('homeAccess')
    }

    void testServerControllerFilter() {

        checkFilter('serverAccess')
    }

    void testLayerControllerFilter() {

        checkFilter('layerAccess')
    }

    void testAllFilter() {

        assertTrue "Write tests", false
    }

    void checkFilter(String filterName) {

        FilterConfig filter = initFilter(filterName)
        assertNotNull filterName + " filter should exist", filter
        assertExistsBefore(filterName)

        assertEquals "accessAllowed should be null to start with", null, filter.request.accessAllowed

        // Run filter
        filter.before()

        assertEquals "accessAllowed should be true now", true, filter.request.accessAllowed
    }
}

Исключение

Проблема заключается в том, что при выполнении этого теста я получаю следующее исключение:

No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at grails.test.MockUtils$_addCommonWebProperties_closure32.doCall(MockUtils.groovy:316)
    at shiro.SecurityFilters$_closure1_closure5_closure12.doCall(SecurityFilters.groovy:40)
    at shiro.SecurityFilters$_closure1_closure5_closure12.doCall(SecurityFilters.groovy)
    at shiro.SecurityFiltersTests.checkFilter(SecurityFiltersTests.groovy:92)
    at shiro.SecurityFiltersTests$checkFilter.callCurrent(Unknown Source)
    at shiro.SecurityFiltersTests.testLayerControllerFilter(SecurityFiltersTests.groovy:65)

Кроме того, я поместил следующую строку в модульном тесте:

println "filter.request: " + filter.request

, которая печатает следующее:

filter.request: org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest@2914cca4

Так что, похоже, он использует объект запроса фиктивного запроса.

Итак, вопросы.

Правильно ли я использую FiltersUnitTestCase для выполнения моих фильтров?

И, если так:

Почему я испытываю это исключение?

1 Ответ

1 голос
/ 10 октября 2011

Напоминание о правилах отладки для всех присутствующих: Продолжайте удалять код, пока не найдете точную строку, в которой находится проблема. Даже если очевидно, что линия не вызывает проблемы. Потому что: иногда это действительно .

Как часть моей работы по отладке, в моем фильтре была следующая строка кода:

println "controllerName = '${controllerName}', actionName = '${actionName}'"

Это было прямо перед строкой:

request.accessAllowed = true

Я взял его из кода, вставленного в этот вопрос, чтобы попытаться сохранить его в чистоте, но, очевидно, я не пытался закомментировать его при запуске тестов. Извините всех, кто изучил этот код и не смог найти проблему. Вы были правы, проблема была не в коде, который я предоставил.

Таким образом, ответ вы можете увидеть исключение, о котором здесь сообщается, если попытаетесь получить доступ к controllerName или actionName переменным .

Решение состоит в том, чтобы использовать методы setControllerName() и setActionName() в FiltersUnitTestCase перед выполнением любого фильтра, который может ссылаться на controllerName или actionName.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...