我一直在为一个简单的spring Web应用程序编写一些简单的单元测试例程.当我在资源的getter方法上添加@JsonIgnore注释时,生成的json对象不包含相应的json元素.因此,当我的单元测试例程尝试测试它是否为null(这是我的情况的预期行为,我不希望密码在json对象中可用)时,测试例程会遇到异常:
java.lang.AssertionError:JSON路径没有值:$ .password,exception:路径没有结果:$ ['password']
这是我编写的单元测试方法,用is(nullValue())方法测试'password'字段:
@Test
public void getUserThatExists() throws Exception {
User user = new User();
user.setId(1L);
user.setUsername("zobayer");
user.setPassword("123456");
when(userService.getUserById(1L)).thenReturn(user);
mockMvc.perform(get("/users/1"))
.andExpect(jsonPath("$.username", is(user.getUsername())))
.andExpect(jsonPath("$.password", is(nullValue())))
.andExpect(jsonPath("$.links[*].href", hasItem(endsWith("/users/1"))))
.andExpect(status().isOk())
.andDo(print());
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用jsonPath().exists()获得类似的异常,说明路径不存在.我正在分享更多的代码片段,以便整个情况变得更具可读性.
我正在测试的控制器方法看起来像这样:
@RequestMapping(value="/users/{userId}", method= RequestMethod.GET)
public ResponseEntity<UserResource> getUser(@PathVariable Long userId) {
logger.info("Request arrived for getUser() with params {}", userId);
User user = userService.getUserById(userId);
if(user != null) {
UserResource userResource = new UserResourceAsm().toResource(user);
return new ResponseEntity<>(userResource, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
Run Code Online (Sandbox Code Playgroud)
我使用spring hateos资源汇编程序将实体转换为资源对象,这是我的资源类:
public class …Run Code Online (Sandbox Code Playgroud) 我的带@ControllerAdvice注释的控制器看起来像这样:
@ControllerAdvice
public class GlobalControllerExceptionHandler {
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
@ExceptionHandler(AuthenticationException.class)
public void authenticationExceptionHandler() {
}
}
Run Code Online (Sandbox Code Playgroud)
当然我的开发是测试驱动的,我想在JUnit测试中使用我的异常处理程序.我的测试用例如下所示:
public class ClientQueriesControllerTest {
private MockMvc mockMvc;
@InjectMocks
private ClientQueriesController controller;
@Mock
private AuthenticationService authenticationService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void findAllAccountRelatedClientsUnauthorized() throws Exception {
when(authenticationService.validateAuthorization(anyString())).thenThrow(AuthenticationException.class);
mockMvc.perform(get("/rest/clients").header("Authorization", UUID.randomUUID().toString()))
.andExpect(status().isUnauthorized());
}
}
Run Code Online (Sandbox Code Playgroud)
可能我需要注册ControllerAdvice课程.怎么做?
有没有人有任何提示,或者有人知道如何测试HTTP响应对象返回的"错误消息"吗?
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
Run Code Online (Sandbox Code Playgroud)
响应:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Run Code Online (Sandbox Code Playgroud) 我很难弄清楚如何在spring mvc中的JSON文档响应中使用jsonPath断言.也许有比使用jsonPath更好的方法来完成这个特定的场景.我想验证链接数组是否具有"self"的rel项,而"self"对象的"href"属性也具有等于"/"的"href"属性.JSON响应如下所示:
{
"links":[
{
"rel":[
"self"
],
"href":"/"
},
{
"rel":[
"next"
],
"href":"/1"
}
]
}
Run Code Online (Sandbox Code Playgroud)
我试过这个,我可以看到它有rel [0]有自己,但我宁愿不依赖于链接数组中的位置和自我的rel数组,并实际测试链接中的href是什么[rel] [self]是"/".有任何想法吗?
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(welcomeController).build();
}
@Test
public void givenRootUrl_thenReturnLinkToSelf() throws Exception {
mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.links[0].rel[0].", is("self")));
}
Run Code Online (Sandbox Code Playgroud) 在使用Spring MockMVC的JUnit测试中,有两种方法可以作为Spring Security用户进行身份验证:@WithMockUser使用提供的凭据创建虚拟用户,@WithUserDetails获取用户的名称并UserDetails使用自定义UserDetailsService(the UserDetailsServiceImpl)将其解析为正确的自定义实现.
在我的例子中,UserDetailsService从数据库加载用户.我想要使用的用户插入@Before了测试套件的方法中.
但是,我UserDetailsServiceImpl找不到用户.
在我@Before,我插入这样的用户:
User u = new User();
u.setEMail("test@test.de");
u = userRepository.save(u);
Run Code Online (Sandbox Code Playgroud)
并在UserDetailsServiceImpl:
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userRepository.findOneByEMail(username);
if (user == null)
throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
return user;
}
Run Code Online (Sandbox Code Playgroud)
如何使用创建的帐户@Before有@WithUserDetails?
我正在尝试在我的REST API中对登录和安全性进行单元测试,因此我尝试尽可能接近地模拟现实生活中的请求序列.
我的第一个请求是:
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).
addFilters(springSecurityFilterChain).build();
this.mapper = new ObjectMapper();
....
MvcResult result=mockMvc.perform(get("/login/csrf")).andExpect(status().is(200)).andReturn();
Cookie[] cookies = result.getResponse().getCookies();
Run Code Online (Sandbox Code Playgroud)
(参见关于pastebin的完整课程).
我尝试在这里获取cookie以便稍后能够使用收到的CSRF令牌登录,但是cookies数组是空的!
但是,如果我运行我的应用程序并打电话
curl -i http://localhost:8080/login/csrf
Run Code Online (Sandbox Code Playgroud)
我确实得到了一个Set-Cookie标头,可以稍后使用该cookie(以及CSRF令牌)进行身份验证.
所以问题是:我如何让MockMvc向我返回一个cookie?
我在使用MockMvc测试Spring Boot应用程序时遇到了一些麻烦.
我有以下测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {SpringConfiguration.class, SecurityConfiguration.class})
@IntegrationTest({"server.port=8080"})
@WebAppConfiguration
public class DemoTest {
@Autowired
private EmbeddedWebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGetAccountUnauthenticated() throws Exception {
mockMvc.perform(get("/accounts/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
}
}
Run Code Online (Sandbox Code Playgroud)
这导致HTTP 200而不是401.我启用了组件扫描和自动配置,并在我的SecuityConfiguration类中配置了spring安全性,如下所示:
@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity // required for use of @AuthenticationPrincipal in MVC controllers.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.debug(true);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//set …Run Code Online (Sandbox Code Playgroud) spring-security spring-test spring-test-mvc spring-boot mockmvc
我有方法的控制器PUT方法,它接收multipart/form-data:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
Run Code Online (Sandbox Code Playgroud)
我想用它来测试它MockMvc.不幸的是,MockMvcRequestBuilders.fileUpload基本上创建了MockMultipartHttpServletRequestBuilder一个POST方法:
super(HttpMethod.POST, urlTemplate, urlVariables)
Run Code Online (Sandbox Code Playgroud)
编辑:
我一定能 ,我不能创建自己的实现MockHttpServletRequestBuilder,比如
public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
Run Code Online (Sandbox Code Playgroud)
因为MockHttpServletRequestBuilder有包本地构造函数.
但我想知道是否更方便有任何方法可以做到这一点,可能是我错过了一些现有的课程或方法吗?
我正在使用MockRestServiceServer在我的REST控制器上编写某种集成测试来模拟后端行为.我现在想要实现的是模拟来自后端的非常慢的响应,这最终会导致我的应用程序超时.它似乎可以用WireMock实现,但目前我想坚持使用MockRestServiceServer.
我正在创建这样的服务器:
myMock = MockRestServiceServer.createServer(asyncRestTemplate);
Run Code Online (Sandbox Code Playgroud)
然后我嘲笑我的后端行为,如:
myMock.expect(requestTo("http://myfakeurl.blabla"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));
Run Code Online (Sandbox Code Playgroud)
是否有可能在响应中添加某种延迟或超时或其他类型的延迟(或者可能是整个模拟服务器甚至是我的asyncRestTemplate)?或者我应该切换到WireMock还是Restito?
我正在尝试测试一些受保护的端点的安全配置@PreAuthorize(#oauth2.hasScope('scope').当通过Postman使用不具有所需范围的访问令牌访问此类端点时,将返回以下HTTP状态码403(禁止):
{
"error": "insufficient_scope",
"error_description": "Insufficient scope for this resource",
"scope": "scope"
}
Run Code Online (Sandbox Code Playgroud)
这是我想要的预期行为.
在尝试测试此配置时,Springs会NestedServletException干扰我的测试用例,然后才能完成预期的结果.
这是我要测试的控制器的简化版本:
@RestController
@RequestMapping(value = "/api")
public class OauthTestingResource {
@PreAuthorize(#oauth2.hasScope('scope'))
@RequestMapping(value = "/scope", method = RequestMethod.GET)
public void endpoint() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这是相应的测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MyApplication.class)
@WebAppConfiguration
public class AuthorizationTest {
@Autowired
protected WebApplicationContext webApplicationContext;
protected SecurityContext securityContext = Mockito.mock(SecurityContext.class);
@Before
public void setup() throws Exception {
this.mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
SecurityContextHolder.setContext(securityContext);
}
protected Authentication createMockAuth(Client …Run Code Online (Sandbox Code Playgroud) mockmvc ×10
java ×6
spring ×6
spring-mvc ×4
junit ×3
jsonpath ×2
unit-testing ×2
cookies ×1
mocking ×1
mockito ×1
spring-boot ×1
spring-test ×1