[笔记] Java 测试的一些注解
@InjectMocks
模拟一个对象,该对象内部的其他对象可以被 @Mock 注入,没有被注入的对象被设置为 null
@Mock
模拟一个对象,该对象内部的其他对象被设置为 null
@MockBean
这个是 SpringBoot 的注解,和 @Mock 类似,但会替代 SpringBoot 的 Bean,比如 @Autowired 指定的 Bean 就会被这个模拟对象替换
@RunWith(SpringRunner.class)
替换默认的 Runner,比如使用 Spring 的 runner,另外 SpringJUnit4ClassRunner 和 SpringRunner 是一样的
@SpringBootTest
创建 spring boot application context,会初始化定义的 Bean,比如 @Autowired 对象 ,比如 @Value 导入的配置,会导致程序启动慢,做的事比较多
@DirtiesContext
在测试的类或方法的前后,清理 application context,默认是 after class 清理,可以防止不同测试之间互相干扰
@ActiveProfiles("test")
指定配置文件为 application-test.yml
@WebAppConfiguration
加载 web application context 通常用于 controller 的测试
@AutoConfigureMockMvc
自动配置 MockMvc 的单元测试,用于 MVC 测试
@Autowired
private MockMvc mvc;
@Test
public void test() throws Exception{
MvcResult mvcResult = mvc
.perform(MockMvcRequestBuilders
.post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(body))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
}
用于发送和验证 http 请求
WireMockRule : 模拟外部 server
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>${version.wiremock}</version>
<scope>test</scope>
</dependency>
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.common.ConsoleNotifier;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
@ClassRule
public static WireMockRule serverSimulator = new WireMockRule(wireMockConfig()
.port(9000).notifier(new ConsoleNotifier(false)));
@Test
public void test() throws Exception {
// 重置
serverSimulator.resetRequests();
// 配置 server 要接收的请求和返回的内容
serverSimulator.stubFor(
post(urlPathMatching(url))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(response)));
// 执行测试代码
// 验证 server 收到的请求
serverSimulator.verify(invokedTimes,
postRequestedFor(urlPathMatching(url))
.withHeader("Authorization", WireMock.matching(auth))
.withRequestBody(containing(request)));
}
这样避免了自己再编写运行模拟 server 的程序
PowerMockito
有些函数 Mockito 无法处理,比如 static,final(不能被子类覆盖的函数),native(其他语言实现的函数),constructor
PowerMockito 可以 mock 这些函数
// @PrepareForTest 指定需要用 PowerMockito 进行 mock 的类,可以注解在测试类,也可以注解在测试函数
// @RunWith(PowerMockRunner.class) 的测试类依然可以使用 Mockito
// @PowerMockIgnore 注解的包不会被 PowerMockito 的类加载器加载,而是被系统的类加载器加载,主要是一些和 xml 交互的类容易出 classloader 错误
// @SuppressStaticInitializationFor 不要执行静态代码
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassA.class, ClassB.class})
@PowerMockIgnore({"org.apache.logging.log4j.*", "com.sun.org.apache.xerces.*"})
@SuppressStaticInitializationFor("com.xxx.xxx.ClassA")
// PowerMockito.mock 创建的可以 mock 静态/final/constructor 等函数
ClassA class = PowerMockito.mock(ClassA.class);
// PowerMockito.when 其实是直接调 Mockito.when,所以用 Mockito.when 也可以
PowerMockito.when(class.get(any(), any())).thenReturn("");
PowerMockito.whenNew(ClassA.class).withNoArguments().thenReturn(obj);
PowerMockito.mockStatic(ClassA.class);
PowerMockito.when(ClassA.staticMethod()).thenAnswer(
invocationOnMock -> {
System.out.println("test");
return null;
}
);
// 如果是 void 函数,应该用另外一种方式
doNothing().when(mockObject).mockMethod(any());
doAnswer(answer).when(mockObject).mockMethod(any());
PowerMockito 可以和 Mockito 一起用
@WebMvcTest
@WebFluxTest
@DataJpaTest
@DataJdbcTest