2011-09-25 73 views
4

更新:我改變了這個問題是關於我遇到的具體問題。這是因爲過濾器的單元測試將在Grails 2.0中得到支持,所以希望文檔會更好。使用FiltersUnitTestCase來單元測試Shiro安全過濾器,IllegalStateException

我想爲我設置的過濾器編寫單元測試,在我的grails應用程序中實現Shiro安全。我正在使用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) 
      } 
     } 
    } 
} 

單元測試

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.code[email protected]2914cca4 

所以它肯定好像是用一個模擬請求對象。

所以,這些問題。

我是否正確使用FiltersUnitTestCase來執行我的過濾器?

而且,如果是這樣:

爲什麼我遇到了這個例外?

回答

1

提醒所有人的調試規則:繼續刪除代碼,直到找到問題的確切路線。即使很明顯該線路不會引起問題。因爲:有時它實際上是

由於我的調試工作的一部分,我的代碼在我的過濾器下面一行:

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

這是直接前行:

request.accessAllowed = true 

我採取了它的代碼粘貼到這個問題,試圖保持它的整潔,但顯然我運行測試時沒有嘗試過評論它。很抱歉,任何查看該代碼並找不到問題的人都可以。你是對的,問題不在我提供的任何代碼中。

所以答案是如果您嘗試訪問controllerNameactionName變量,您可能會看到此處報告的異常。

的解決方案是執行該可能引用controllerNameactionName任何過濾器之前,使用中的FiltersUnitTestCase和setControllerName()setActionName()方法。