45.3.4使用模拟环境进行测试
默认情况下, @SpringBootTest 无法启动服务器。如果您要针对此模拟环境测试Web端点,则可以另外进行配置 MockMvc ,如以下示例所
示:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockMvcExampleTests {
@Autowired
private MockMvc mvc;
@Test
public void exampleTest() throws Exception {
this.mvc.perform(get("/")).andExpect(status().isOk())
.andExpect(content().string("Hello World"));
}
}
如果您只想关注网络层而不是开始一个完整的 ApplicationContext ,请考虑 使用 @WebMvcTest 。
45.3.5使用正在运行的服务器进行测试
如果您需要启动完整运行的服务器,我们建议您使用随机端口。如果使
用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) ,则每次测试运行时随机选择一个可用端口。
@LocalServerPort 注释可用于 注入测试中使用的实际端口。为方便起见,需要对启动的服务器进行REST调用的测试还可以 @Autowire a
WebTestClient ,它解析了与正在运行的服务器的相对链接,并附带了用于验证响应的专用API,如以下示例所示:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortWebTestClientExampleTests {
@Autowired
private WebTestClient webClient;
@Test
public void exampleTest() {
this.webClient.get().uri("/").exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello World");
}
}
此设置在类路径上需要 spring-webflux 。如果您不能或不会添加webflux,Spring Boot还提供 TestRestTemplate 设施:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortTestRestTemplateExampleTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void exampleTest() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
45.3.6使用JMX
当测试上下文框架缓存上下文时,默认情况下禁用JMX以防止相同的组件在同一域上注册。如果此类测试需要访问 MBeanServer ,请考虑将其
标记为脏:
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
public class SampleJmxTests {
@Autowired
private MBeanServer mBeanServer;
@Test
public void exampleTest() {
// ...
}
}
45.3.7嘲弄和间谍活动Beans
运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,您可能拥有在开发期间不可用的某些远程服务的外观。当您想要模拟在真实环
境中可能难以触发的故障时,模拟也很有用。
Spring Boot包含 @MockBean 注释,可用于为 ApplicationContext 内的bean定义Mockito模拟。您可以使用注释添加新的beans或替换单个
现有的bean定义。注释可以直接用于测试类,测试中的字段或 @Configuration 类和字段。在字段上使用时,也会注入创建的模拟的实例。模
拟beans在每种测试方法后自动重置。
如果您的测试使用Spring Boot的测试注释之一(例如 @SpringBootTest ),则会自动启用此功能。要以不同的排列方式使用此
功能,必须显式添加侦听器,如以下示例所示:
@TestExecutionListeners(MockitoTestExecutionListener.class)
以下示例使用模拟实现替换现有的 RemoteService bean:
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import org.springframework.test.context.junit4.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
@MockBean
private RemoteService remoteService;
@Autowired
private Reverser reverser;
@Test
public void exampleTest() {
// RemoteService has been injected into the reverser bean
given(this.remoteService.someCall()).willReturn("mock");
String reverse = reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
}
}
此外,您可以使用 @SpyBean 将任何现有的bean与Mockito spy 包装在一起。有关详细信息,请参阅Javadoc。
虽然Spring的测试框架在测试之间缓存应用程序上下文并重用共享相同配置的测试的上下文,但使用 @MockBean 或 @SpyBean 会
影响缓存密钥,这很可能会增加缓存密钥的数量。上下文。
如果您使用 @SpyBean 监视bean并使用 @Cacheable 方法按名称引用参数,则必须使用 -parameters 编译应用程序。这可以确保
在bean被监视后,参数名称可用于缓存基础结构。