2015-11-04 134 views
7

我想測試一個Spring Boot其餘的控制器,它使用Spring security進行保護,並在其中使用模擬。我曾嘗試過Mockito,但我認爲任何嘲弄工具都應該做到這一點。Spring MockMVC,Spring security and Mockito

爲了使春季安全測試中,我第一次做如下:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Autowired 
    private WebApplicationContext wac; 

    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .webAppContextSetup(wac) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

直到有,它工作得很好。

經過這一步之後,我希望添加mock來隔離測試我的安全控制器。

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Mock 
    private Myservice serviceInjectedInController; 

    @InjectMocks 
    private MyController myController; 

    @Autowired 
    private WebApplicationContext wac; 

    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .webAppContextSetup(wac) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

不幸的是,嘲笑的服務未在控制器注入,因爲沒有涉及的MockMVC和嘲笑什麼,所以嘲笑不會在控制器注入。

所以我試圖改變MockMVC的配置,如下所示:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Main.class) 
@TestPropertySource(value="classpath:application-test.properties") 
@WebAppConfiguration 
@ContextConfiguration 
public class MyTest{ 

    protected MockMvc mockMvc; 

    @Mock 
    private Myservice serviceInjectedInController; 

    @InjectMocks 
    private MyController myController; 


    @Before 
    public void setUp(){ 
     mockMvc = MockMvcBuilders 
       .standAloneSetup(myController) 
       .apply(SecurityMockMvcConfigurers.springSecurity()) 
       .build(); 
    } 

    @Test 
    public void doTheTest(){ 
     mockMvc.perform(post("/user/register") 
      .with(SecurityMockMvcRequestPostProcessors.csrf()) 
      .content(someContent())); 
    } 
} 

但在這種情況下,我有另外一個問題。春季安全是抱怨的配置:

java.lang.IllegalStateException: springSecurityFilterChain cannot be null. Ensure a Bean with the name springSecurityFilterChain implementing Filter is present or inject the Filter to be used. 

我沒有其他的想法,使安全和嘲笑。任何想法?或者我應該採取另一種方式?

謝謝。

+0

您使用Spring Security的4+版本:可以用明確提供springSecurityFilterChain? – Ritesh

+0

我使用的是Spring-boot 1.2.7.RELEASE,我已經覆蓋默認的Spring安全性來使用4.0.2 –

+0

@Remi你有沒有解決這個問題? – hvgotcodes

回答

9

默認情況下,集成查找名稱爲「springSecurityFilterChain」的bean。在提供的示例中,正在使用獨立安裝,這意味着MockMvc將不知道測試中提供的WebApplicationContext,因此無法查找「springSecurityFilterChain」bean。

解決這個最簡單的方法就是用這樣的:

MockMvc mockMvc = MockMvcBuilders 
      // replace standaloneSetup with line below 
      .webAppContextSetup(wac) 
      .alwaysDo(print()) 
      .apply(SecurityMockMvcConfigurers.springSecurity()) 
      .build(); 

如果你真的想使用standaloneSetup(並沒有真正意義的,因爲你已經有一個WebApplicationContext的),你

@Autowired 
FilterChainProxy springSecurityFilterChain; 

@Before 
public void startMocks(){ 
    controller = wac.getBean(RecipesController.class); 

    MockMvc mockMvc = MockMvcBuilders 
      .standaloneSetup(controller) 
      .alwaysDo(print()) 
      .apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain)) 
      .build(); 

    MockitoAnnotations.initMocks(this); 
} 
+0

告訴我,如果我錯了,但使用'standaloneSetup'是控制器上有足夠的控制權以便能夠注入Mocks的唯一方法。還是有另一種方式? –

+0

您可以創建一個測試配置,爲您的服務提供模擬。然後排除具有實際服務的配置。或者,您可以使用這兩種配置,並在模擬版本的服務上標記'@ Primary'。爲了設置期望並驗證你可以'@ Autowire'中的模擬服務。 –