本文目录导读:

我来教你用Java注解实现一个简单的测试框架,这个框架会包含自定义注解、测试执行器和示例测试类。
自定义注解定义
测试方法注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 标记为测试方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
// 测试用例描述
String description() default "";
// 是否忽略该测试
boolean ignore() default false;
}
测试前置/后置注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterClass {
}
测试执行器
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class TestRunner {
private int passed = 0;
private int failed = 0;
private List<String> failureMessages = new ArrayList<>();
public void runTests(Class<?> testClass) {
System.out.println("=== 开始执行测试: " + testClass.getSimpleName() + " ===");
try {
// 获取所有方法
Method[] methods = testClass.getDeclaredMethods();
// 收集各类型方法
List<Method> beforeClassMethods = new ArrayList<>();
List<Method> afterClassMethods = new ArrayList<>();
List<Method> beforeMethods = new ArrayList<>();
List<Method> afterMethods = new ArrayList<>();
List<Method> testMethods = new ArrayList<>();
for (Method method : methods) {
if (method.isAnnotationPresent(BeforeClass.class)) {
beforeClassMethods.add(method);
}
if (method.isAnnotationPresent(AfterClass.class)) {
afterClassMethods.add(method);
}
if (method.isAnnotationPresent(Before.class)) {
beforeMethods.add(method);
}
if (method.isAnnotationPresent(After.class)) {
afterMethods.add(method);
}
if (method.isAnnotationPresent(Test.class)) {
Test testAnnotation = method.getAnnotation(Test.class);
if (!testAnnotation.ignore()) {
testMethods.add(method);
} else {
System.out.println(" 忽略测试: " + method.getName());
}
}
}
// 执行 BeforeClass
Object testInstance = testClass.getDeclaredConstructor().newInstance();
for (Method method : beforeClassMethods) {
method.invoke(testInstance);
}
// 执行每个测试方法
for (Method testMethod : testMethods) {
// 为每个测试创建新实例,保证独立
Object instance = testClass.getDeclaredConstructor().newInstance();
// 执行 Before
for (Method method : beforeMethods) {
method.invoke(instance);
}
// 执行测试
Test testAnnotation = testMethod.getAnnotation(Test.class);
String description = testAnnotation.description().isEmpty() ?
testMethod.getName() : testAnnotation.description();
System.out.print(" 测试: " + description + " ... ");
try {
testMethod.invoke(instance);
System.out.println("通过");
passed++;
} catch (Exception e) {
System.out.println("失败");
failed++;
String failureMessage = testMethod.getName() + " 失败: " +
e.getCause().getMessage();
failureMessages.add(failureMessage);
}
// 执行 After
for (Method method : afterMethods) {
method.invoke(instance);
}
}
// 执行 AfterClass
for (Method method : afterClassMethods) {
method.invoke(testInstance);
}
} catch (Exception e) {
System.err.println("测试框架错误: " + e.getMessage());
e.printStackTrace();
}
// 打印测试结果
printResults();
}
private void printResults() {
System.out.println("\n=== 测试结果 ===");
System.out.println("通过: " + passed);
System.out.println("失败: " + failed);
System.out.println("总计: " + (passed + failed));
if (!failureMessages.isEmpty()) {
System.out.println("\n失败详情:");
for (String message : failureMessages) {
System.out.println(" - " + message);
}
}
}
}
断言工具类
public class Assert {
public static void assertEquals(Object expected, Object actual) {
if (!expected.equals(actual)) {
throw new AssertionError(
"期望值: " + expected + ", 实际值: " + actual);
}
}
public static void assertTrue(boolean condition) {
if (!condition) {
throw new AssertionError("条件不成立");
}
}
public static void assertFalse(boolean condition) {
if (condition) {
throw new AssertionError("条件应该为false");
}
}
public static void assertNull(Object object) {
if (object != null) {
throw new AssertionError("对象应该为null");
}
}
public static void assertNotNull(Object object) {
if (object == null) {
throw new AssertionError("对象不应该为null");
}
}
}
使用示例
被测试的类
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
public int multiply(int a, int b) {
return a * b;
}
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("除数不能为0");
}
return a / b;
}
}
测试类
public class CalculatorTest {
private Calculator calculator;
@Before
public void setUp() {
System.out.println(" 设置测试环境");
calculator = new Calculator();
}
@After
public void tearDown() {
System.out.println(" 清理测试资源");
calculator = null;
}
@BeforeClass
public static void initClass() {
System.out.println(" 初始化测试类");
}
@AfterClass
public static void destroyClass() {
System.out.println(" 销毁测试类");
}
@Test(description = "测试加法功能")
public void testAdd() {
Assert.assertEquals(5, calculator.add(2, 3));
Assert.assertEquals(0, calculator.add(-1, 1));
Assert.assertEquals(-5, calculator.add(-2, -3));
}
@Test(description = "测试减法功能")
public void testSubtract() {
Assert.assertEquals(3, calculator.subtract(5, 2));
Assert.assertEquals(-3, calculator.subtract(2, 5));
}
@Test(description = "测试乘法功能")
public void testMultiply() {
Assert.assertEquals(6, calculator.multiply(2, 3));
Assert.assertEquals(0, calculator.multiply(0, 5));
Assert.assertEquals(-6, calculator.multiply(-2, 3));
}
@Test(description = "测试除法功能")
public void testDivide() {
Assert.assertEquals(2, calculator.divide(6, 3));
Assert.assertEquals(0, calculator.divide(1, 3));
}
@Test(description = "测试除以零异常", ignore = true)
public void testDivideByZero() {
try {
calculator.divide(1, 0);
Assert.assertTrue(false); // 不应该执行到这里
} catch (IllegalArgumentException e) {
// 期望的异常
}
}
}
运行测试
public class Main {
public static void main(String[] args) {
// 创建测试运行器
TestRunner runner = new TestRunner();
// 运行测试
runner.runTests(CalculatorTest.class);
// 可以运行其他测试类
// runner.runTests(UserServiceTest.class);
}
}
运行结果
=== 开始执行测试: CalculatorTest ===
初始化测试类
测试: 测试加法功能 ...
设置测试环境
清理测试资源
通过
测试: 测试减法功能 ...
设置测试环境
清理测试资源
通过
测试: 测试乘法功能 ...
设置测试环境
清理测试资源
通过
测试: 测试除法功能 ...
设置测试环境
清理测试资源
通过
忽略测试: testDivideByZero
销毁测试类
=== 测试结果 ===
通过: 4
失败: 0
总计: 4
扩展功能
你还可以添加更多功能:
// 超时注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestTimeout {
long value() default 1000; // 毫秒
}
// 预期异常注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExpectedException {
Class<? extends Throwable> value();
}
这个简单的测试框架演示了Java注解的核心用法:
- 定义注解:使用
@interface和元注解 - 解析注解:通过反射获取注解信息
- 处理注解:根据注解执行相应逻辑
你可以基于这个框架扩展到更复杂的功能,比如支持参数化测试、测试套件、报告生成等。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播