java 在需要身份验证的控制器上运行单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29704428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Run unit tests on controllers that require authentication
提问by aochagavia
I have a spring boot application which requires login for some actions. I am trying to test them using MockMvc
, but it doesn't seem to work. I keep getting a HTTP response with status 403 (forbidden). Probably there is something wrong with the authentication part.
我有一个 Spring Boot 应用程序,它需要登录才能执行某些操作。我正在尝试使用 测试它们MockMvc
,但它似乎不起作用。我不断收到状态为 403(禁止)的 HTTP 响应。认证部分可能有问题。
I have tried following the documentation, but I wasn't able to get it working.
我已尝试按照文档进行操作,但无法使其正常工作。
This is my current testing code:
这是我当前的测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class})
@WebIntegrationTest("server.port = 8093")
public class PasswordChangeTests {
@Autowired
private EmbeddedWebApplicationContext webApplicationContext;
@Autowired
private UserRepository userRepository;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
}
@Test
public void changePasswordWorks() throws Exception {
// Send password change request
PasswordChangeRepresentation passwordChange = new PasswordChangeRepresentation(DefaultUsers.Admin.getPassword(), "12345678");
mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/password/change")
.content(new ObjectMapper().writeValueAsString(passwordChange))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
// Check that the password has been changed
User user = this.userRepository.findByUsername(DefaultUsers.Admin.getEmail());
Assert.assertEquals(user.getPassword(), "12345678");
}
}
Sorry if I am missing something obvious. This is my first experience with spring boot.
对不起,如果我遗漏了一些明显的东西。这是我第一次体验spring boot。
回答by Rob Winch
You need to specify which user you want to run the test as. You have a few options (each option is a link to the detailed documentation):
您需要指定要以哪个用户身份运行测试。您有几个选项(每个选项都是详细文档的链接):
This option will create a fake user (i.e. the user does not need to exist in a data store). The problem with this approach is if your application relies on a custom User implementation you may get class cast Exceptions. If you do not return a custom type from a custom UserDetailsService, then this solution should work fine.
此选项将创建一个假用户(即该用户不需要存在于数据存储中)。这种方法的问题是,如果您的应用程序依赖于自定义用户实现,您可能会遇到类转换异常。如果您不从自定义 UserDetailsService 返回自定义类型,则此解决方案应该可以正常工作。
@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void changePasswordWorks() throws Exception {
If you implemented a custom UserDetailsService that returns a custom implementation of UserDetails, this solution may work for you.
如果您实现了返回 UserDetails 的自定义实现的自定义 UserDetailsService,则此解决方案可能适合您。
For it to work you need to expose a UserDetailsService as a Bean and the user must exist. For example:
要使其工作,您需要将 UserDetailsService 公开为 Bean,并且用户必须存在。例如:
@Test
@WithUserDetails("admin")
public void changePasswordWorks() throws Exception {
This is the best of both worlds, but requires a little additional setup. If you have a custom UserDetailsService returning a custom implementation of UserDetails and do NOT want the user to necessarily have to exist you can use this method. I'll let you read the documentation on this setup as it is a bit more lengthy and well documented.
这是两全其美的方法,但需要一些额外的设置。如果您有自定义 UserDetailsService 返回 UserDetails 的自定义实现,并且不希望用户必须存在,则可以使用此方法。我会让您阅读有关此设置的文档,因为它有点冗长且文档齐全。
If annotations aren't your thing you can use a RequestPostProcessor. For example:
如果注释不是你的东西,你可以使用 RequestPostProcessor。例如:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
...
@Test
public void changePasswordWorks() throws Exception {
// Send password change request
PasswordChangeRepresentation passwordChange = new PasswordChangeRepresentation(DefaultUsers.Admin.getPassword(), "12345678");
mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/password/change")
// ADD this line
.with(user("admin").roles("USER","ADMIN"))
.content(new ObjectMapper().writeValueAsString(passwordChange))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
// Check that the password has been changed
User user = this.userRepository.findByUsername(DefaultUsers.Admin.getEmail());
Assert.assertEquals(user.getPassword(), "12345678");
}