Spring 使用 Mockito 启动测试:@Validated 注释在单元测试期间被忽略
Spring Boot Test with Mockito : @Validated annotation is being ignored during unit tests
我正在使用 Spring Boot 2.1.1、JUnit 5、Mockito 2.23.4。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
这是我的控制器:
@RestController
@Validated
public class AramaController {
@ResponseStatus(value = HttpStatus.OK)
@GetMapping("/arama")
public List<Arama> arama(@RequestParam @NotEmpty @Size(min = 4, max = 20) String query) {
return aramaService.arama(query);
}
}
此控制器按预期工作。
没有 "query" 参数的 curl returns 错误请求 400 :
~$ curl http://localhost:8080/arama -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /arama HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 400
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Wed, 12 Dec 2018 21:47:11 GMT
< Connection: close
<
* Closing connection 0
使用 "query=a" 作为参数的 curl returns 错误请求 400 以及:
~$ curl http://localhost:8080/arama?query=a -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /arama?query=a HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 400
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 12 Dec 2018 21:47:33 GMT
< Connection: close
<
* Closing connection 0
{"message":"Input error","details":["size must be between 4 and 20"]}
当 运行 在服务器上时,此控制器和验证工作完美。
在单元测试期间,@Validated 注释似乎没有任何效果。
这是我的测试代码:
@ExtendWith(MockitoExtension.class)
class AramaControllerTest {
@Mock
private AramaService aramaService;
@InjectMocks
private AramaController aramaController;
private MockMvc mockMvc;
@BeforeEach
private void setUp() {
mockMvc = MockMvcBuilders
.standaloneSetup(aramaCcontroller)
.setControllerAdvice(new RestResponseEntityExceptionHandler())
.build();
}
@Test
void aramaValidationError() throws Exception {
mockMvc
.perform(
get("/arama").param("query", "a")
)
.andExpect(status().isBadRequest());
verifyNoMoreInteractions(aramaService);
}
}
此测试失败:
java.lang.AssertionError: Status expected:<400> but was:<200>
Expected :400
Actual :200
由于 @Valid 注释通过了我的其他测试用例,并且它们在不加载 Spring 上下文的情况下工作,有没有办法使 @Validated 注释与 Mockito 一起工作(同样,不加载Spring 上下文)?
也许你可以尝试使用 @WebMvcTest
并添加 SpringExtension
@ExtendWith({SpringExtension.class, MockitoExtension.class})
@WebMvcTest(AramaController.class)
class AramaControllerTest {
@Mock
private AramaService aramaService;
@InjectMocks
private AramaController aramaController;
@Autowired
private MockMvc mockMvc;
@Test
void aramaValidationError() throws Exception {
mockMvc
.perform(
get("/arama").param("query", "a")
)
.andExpect(status().isBadRequest());
verifyNoMoreInteractions(aramaService);
}
}
我在别处得到了答案,想分享一下:
Without starting up the context, you won't have @Validator getting
tested because validator instances are Spring beans. However, @Valid
will work as it is a JSR-303 standard.
As of now, what I can suggest is.
@SpringBootTest
@ExtendWith(SpringExtension.class)
我正在使用 Spring Boot 2.1.1、JUnit 5、Mockito 2.23.4。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
这是我的控制器:
@RestController
@Validated
public class AramaController {
@ResponseStatus(value = HttpStatus.OK)
@GetMapping("/arama")
public List<Arama> arama(@RequestParam @NotEmpty @Size(min = 4, max = 20) String query) {
return aramaService.arama(query);
}
}
此控制器按预期工作。
没有 "query" 参数的 curl returns 错误请求 400 :
~$ curl http://localhost:8080/arama -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /arama HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 400
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Wed, 12 Dec 2018 21:47:11 GMT
< Connection: close
<
* Closing connection 0
使用 "query=a" 作为参数的 curl returns 错误请求 400 以及:
~$ curl http://localhost:8080/arama?query=a -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /arama?query=a HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 400
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 12 Dec 2018 21:47:33 GMT
< Connection: close
<
* Closing connection 0
{"message":"Input error","details":["size must be between 4 and 20"]}
当 运行 在服务器上时,此控制器和验证工作完美。
在单元测试期间,@Validated 注释似乎没有任何效果。
这是我的测试代码:
@ExtendWith(MockitoExtension.class)
class AramaControllerTest {
@Mock
private AramaService aramaService;
@InjectMocks
private AramaController aramaController;
private MockMvc mockMvc;
@BeforeEach
private void setUp() {
mockMvc = MockMvcBuilders
.standaloneSetup(aramaCcontroller)
.setControllerAdvice(new RestResponseEntityExceptionHandler())
.build();
}
@Test
void aramaValidationError() throws Exception {
mockMvc
.perform(
get("/arama").param("query", "a")
)
.andExpect(status().isBadRequest());
verifyNoMoreInteractions(aramaService);
}
}
此测试失败:
java.lang.AssertionError: Status expected:<400> but was:<200>
Expected :400
Actual :200
由于 @Valid 注释通过了我的其他测试用例,并且它们在不加载 Spring 上下文的情况下工作,有没有办法使 @Validated 注释与 Mockito 一起工作(同样,不加载Spring 上下文)?
也许你可以尝试使用 @WebMvcTest
并添加 SpringExtension
@ExtendWith({SpringExtension.class, MockitoExtension.class})
@WebMvcTest(AramaController.class)
class AramaControllerTest {
@Mock
private AramaService aramaService;
@InjectMocks
private AramaController aramaController;
@Autowired
private MockMvc mockMvc;
@Test
void aramaValidationError() throws Exception {
mockMvc
.perform(
get("/arama").param("query", "a")
)
.andExpect(status().isBadRequest());
verifyNoMoreInteractions(aramaService);
}
}
我在别处得到了答案,想分享一下:
Without starting up the context, you won't have @Validator getting tested because validator instances are Spring beans. However, @Valid will work as it is a JSR-303 standard.
As of now, what I can suggest is.
@SpringBootTest @ExtendWith(SpringExtension.class)