UT 上手实践
基本工具
Tools
- Junit——Java主流单元测试框架
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit Platform:测试框架基础,定义了TestEngine用于开发在平台上运行的测试框架的API。
JUnit Jupiter:JUnit5的核心,是一个基于JUnit Platform的引擎实现,它包含许多丰富的新特性来使得自动化测试更加方便和强大。
JUnit Vintage:兼容JUnit3、JUnit4版本的测试引擎,使得旧版本的自动化测试也可以在JUnit5下正常运行。
- Mockito——Java单元测试Mock框架
Annotations
注解 | 描述 |
---|---|
@Test | 测试方法 |
@DisplayName | 自定义显示名称 |
@BeforeAll | 在所有单元测试方法执行之前执行一遍 |
@BeforeEach | 在每个单元测试方法执行前都执行一遍 |
@AfterEach | 在每个单元测试方法执行后都执行一遍 |
@AfterAll | 在所有单元测试方法执行之后执行一遍 |
@Tag | 类或方法上声明的标签,用于过滤测试 |
@Disabled | 禁用测试类或测试方法 |
@Timeout | 执行超过给定的时间,则测试失败。 |
@ParameterizedTest | 参数化测试 |
Assertions
import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.jupiter.api.Test;
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.*;
/**
* AssertionDemoTest
*
* @author yuan
* @since 2021/12/1 09:21
*/
public class AssertionDemoTest {
private final Calculator calculator = new Calculator();
private final Person person = new Person("Jane", "Doe");
@Test
void standardAssertions() {
assertEquals(2, calculator.add(1, 1));
assertEquals(4, calculator.multiply(2, 2),
"The optional failure message is now the last parameter");
assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "
+ "to avoid constructing complex messages unnecessarily.");
}
@Test
void groupedAssertions() {
// In a grouped assertion all assertions are executed, and all
// failures will be reported together.
assertAll("person",
() -> assertEquals("Jane", person.getFirstName()),
() -> assertEquals("Doe", person.getLastName())
);
}
@Test
void dependentAssertions() {
// Within a code block, if an assertion fails the
// subsequent code in the same block will be skipped.
assertAll("properties",
() -> {
String firstName = person.getFirstName();
assertNotNull(firstName);
// Executed only if the previous assertion is valid.
assertAll("first name",
() -> assertTrue(firstName.startsWith("J")),
() -> assertTrue(firstName.endsWith("e"))
);
},
() -> {
// Grouped assertion, so processed independently
// of results of first name assertions.
String lastName = person.getLastName();
assertNotNull(lastName);
// Executed only if the previous assertion is valid.
assertAll("last name",
() -> assertTrue(lastName.startsWith("D")),
() -> assertTrue(lastName.endsWith("e"))
);
}
);
}
@Test
void exceptionTesting() {
Exception exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
}
@Test
void timeoutNotExceeded() {
// The following assertion succeeds.
assertTimeout(ofMinutes(2), () -> {
// Perform task that takes less than 2 minutes.
});
}
@Test
void timeoutNotExceededWithResult() {
// The following assertion succeeds, and returns the supplied object.
String actualResult = assertTimeout(ofMinutes(2), () -> {
return "a result";
});
assertEquals("a result", actualResult);
}
@Test
void timeoutNotExceededWithMethod() {
// The following assertion invokes a method reference and returns an object.
String actualGreeting = assertTimeout(ofMinutes(2), AssertionDemoTest::greeting);
assertEquals("Hello, World!", actualGreeting);
}
@Test
void timeoutExceeded() {
// The following assertion fails with an error message similar to:
// execution exceeded timeout of 10 ms by 91 ms
// 超时-任务执行完毕
assertTimeout(ofMillis(10), () -> {
// Simulate task that takes more than 10 ms.
Thread.sleep(100);
});
}
@Test
void timeoutExceededWithPreemptiveTermination() {
// The following assertion fails with an error message similar to:
// execution timed out after 10 ms
// 超时-则取消任务
assertTimeoutPreemptively(ofMillis(10), () -> {
// Simulate task that takes more than 10 ms.
Thread.sleep(100);
});
}
private static String greeting() {
return "Hello, World!";
}
public static class Calculator {
public int add(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
return a * b;
}
public int divide(int a, int b) {
return a / b;
}
}
@Data
@AllArgsConstructor
public static class Person {
private String firstName;
private String lastName;
}
}
小试牛刀
FirstTest
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* FirstTest
*
* @author yuan
* @since 2021/11/29 10:22
*/
public class FirstTest {
private final Calculator calculator = new Calculator();
@Test
@Tag("fast")
@DisplayName("My 1st JUnit 5 test!