我正在使用 JUnit、Mockito 和 spring-test 测试我的 Spring MVC Controller 。不幸的是,测试忽略了我的 Controller 方法上的 @PreAuthorize 注释,我一直无法解决这个问题。关键代码片段如下,尽管我已经从 MyController 的依赖项中删除了不相关的模拟响应逻辑以保持简短。我正在使用 Spring 3.2 和 JUnit 4,我正在通过 Maven 和直接通过 Eclipse 运行测试(运行方式 -> JUnit 测试)。
现在我预计 getAccounts_ReturnsOkStatus 测试会失败,因为我没有提供任何身份验证,并且/accounts 路由映射到的方法使用预身份验证注释进行注释,但是该方法正在调用并绕过预授权检查。
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 应用程序上下文,因为使用手动身份验证
Authentication auth = new UsernamePasswordAuthenticationToken(name, password);
SecurityContextHolder.getContext().setAuthentication(am.authenticate(auth));
仅适用于测试配置中指定的用户凭据(在没有任何其他身份验证提供程序的情况下)。此外,我可以确定预授权被忽略了,因为我已经使用 SEL 测试过调用方法并进行了调试。
我错过了什么?
最佳答案
构建mockMvc
时必须启用spring security进行测试。
在 Spring 4 中是这样的:
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(springSecurity())
.build();
在 Spring 3 中是这样的:
@Autowired
private Filter springSecurityFilterChain;
...
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(springSecurityFilterChain)
.build();
更多细节见:
关于java - 测试时忽略 Spring Controller 上的 PreAuthorize 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42087496/