在测试

时间:2017-02-07 10:32:28

标签: java spring spring-security mockito junit4

我正在使用JUnit,Mockito& amp;测试我的Spring MVC控制器。弹簧试验。不幸的是,测试忽略了我的控制器方法上的@PreAuthorize注释,我一直无法解决这个问题。下面是关键代码片段,尽管我已经删除了不相关的逻辑,用于模拟来自MyController依赖项的响应以保持简短。我使用的是Spring 3.2& JUnit 4,我通过Maven和Eclipse直接运行测试(Run as - > JUnit test)。

现在我期待 getAccounts_ReturnsOkStatus 测试失败,因为我没有提供任何身份验证,并且/ accounts路由映射到的方法使用pre-auth注释进行注释,但是方法正在被调用并且绕过了预认证检查。

MyControllerTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-test.xml" })
public class MyControllerTest {

    private MockMvc mockMvc;

    @Mock
    private MyService myService;

    @InjectMocks
    private MyController myController;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);  
        mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
    }

   @Test
   public void getAccounts_ReturnsOkStatus() throws Exception {
       // Make the GET request, and verify that it returns HttpStatus.OK (200)
       mockMvc.perform(MockMvcRequestBuilders.get("/accounts"))
              .andExpect(MockMvcResultMatchers.status().isOk());
   }
}

的applicationContext-的test.xml

<sec:global-method-security pre-post-annotations="enabled" />
<bean id="applicationContextProvider" class="com.myapp.springsupport.ApplicationContextProvider" />

<sec:authentication-manager alias="authenticationManager">
   <sec:authentication-provider>
       <sec:user-service>
           <sec:user name="test-superuser" password="test-pwd" authorities="ROLE_SUPERUSER" />
       </sec:user-service>
   </sec:authentication-provider>
</sec:authentication-manager>

MyController.java

@PreAuthorize("isAuthenticated() and hasRole('ROLE_SUPERUSER')")
@RequestMapping(value = "/accounts", method = RequestMethod.GET)
@ResponseBody
public Collection<Account> getAccounts() {
    return new ArrayList<Account>();
}

由于使用

手动验证,因此肯定会使用applicationContext-test app上下文
Authentication auth = new UsernamePasswordAuthenticationToken(name, password);
SecurityContextHolder.getContext().setAuthentication(am.authenticate(auth));

仅适用于测试配置中指定的用户凭据(在没有任何其他身份验证提供程序的情况下)。此外,我可以确定pre-auth被忽略,因为我已经使用SEL测试了一个方法&amp;调试。

我错过了什么?

2 个答案:

答案 0 :(得分:2)

在构建mockMvc时,您必须启用spring security以进行测试。

在春季4,它是这样的:

mockMvc = MockMvcBuilders.webAppContextSetup(context)
                         .apply(springSecurity())
                         .build();

在春季3,它是这样的:

@Autowired
private Filter springSecurityFilterChain;
...
mockMvc = MockMvcBuilders.webAppContextSetup(context)
                         .addFilters(springSecurityFilterChain)
                         .build();

有关详细信息,请参阅:

答案 1 :(得分:-1)

MockMvcBuilders.standaloneSetup手动实例化一个MyController(没有Spring,因此没有AOP)。因此,@PreAuthorize不会被拦截,安全检查将被跳过。因此,您可以@Autowire控制器,并将其传递到MockMvcBuilders.standaloneSetupMyService使用@MockBean的Mock中,以便将服务的每个实例替换为Mock。