首页 > 其他分享 >模拟JUnit框架:创建自定义测试注解和运行器

模拟JUnit框架:创建自定义测试注解和运行器

时间:2024-12-05 17:11:40浏览次数:7  
标签:自定义 MyTest JUnit 注解 annotation public 测试方法

模拟JUnit框架:创建自定义测试注解和运行器

引言

在软件开发中,单元测试是保证代码质量的重要环节。JUnit是一个流行的Java单元测试框架,它提供了@Test注解来标记测试方法,并且有内置的机制来发现并执行这些测试。本文将通过一个简单的例子展示如何使用Java的注解和反射机制模拟JUnit框架的核心功能,即自动发现和执行带有特定注解的方法。

自定义注解与测试类设计

定义MyTest注解

为了实现类似JUnit的功能,我们首先需要定义一个自定义注解@MyTest,该注解仅用于修饰方法,并且可以在运行时被读取。

package com.itcq.annotation.demo3;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 元注解@Target(ElementType.METHOD)确保@MyTest只能修饰方法。
@Target(value = ElementType.METHOD)
// 元注解@Retention(RetentionPolicy.RUNTIME)确保@MyTest在运行时仍然可用。
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyTest {
}

编写测试类

接下来,我们将编写一个目标类MyTestDemo,其中包含三个方法,其中两个用@MyTest注解标记为测试方法。

package com.itcq.annotation.demo3;

public class MyTestDemo {
    // 测试方法1,添加了@MyTest注解,表示这是一个测试方法。
    @MyTest
    public void test1() {
        System.out.println("test1运行~~~");
    }

    // 未标注的方法,不会被视为测试方法。
    public void test2() {
        System.out.println("test2运行~~~");
    }

    // 测试方法3,同样添加了@MyTest注解。
    @MyTest
    public void test3() {
        System.out.println("test3运行~~~");
    }
}

模拟JUnit运行器

最后,我们需要一个调用类App,它将在启动时扫描并执行所有带@MyTest注解的方法,模拟JUnit的行为。

package com.itcq.annotation.demo3;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class App {
    public static void main(String[] args) {
        try {
            // 根据全限定名加载测试类TestMyTest的Class对象。
            Class<?> clazz = Class.forName("com.itcq.annotation.demo3.MyTestDemo");

            // 获取测试类中的所有公共方法(包括继承的方法)。
            Method[] methods = clazz.getMethods();

            // 遍历所有方法,检查是否有@MyTest注解。
            for (Method method : methods) {
                if (method.isAnnotationPresent(MyTest.class)) {
                    // 如果方法上有@MyTest注解,则创建实例并调用该方法。
                    method.invoke(clazz.getDeclaredConstructor().newInstance());
                }
            }
        } catch (ClassNotFoundException e) {
            // 类未找到异常处理。
            e.printStackTrace();
        } catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
            // 方法访问、调用或实例化失败时的异常处理。
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // 构造函数未找到时的异常处理。
            e.printStackTrace();
        }
    }
}

关键点解释

  • 反射API:使用getMethods()获取类的所有公共方法列表,然后通过isAnnotationPresent()判断方法是否被@MyTest注解标记。如果存在这样的注解,我们就使用invoke()方法来执行它。
  • 异常处理:在反射操作过程中可能会遇到各种异常,如ClassNotFoundExceptionInstantiationException等,因此必须妥善处理这些异常以确保程序的稳定性。
  • 实例化:由于invoke()需要一个对象实例来调用非静态方法,所以我们使用clazz.getDeclaredConstructor().newInstance()来创建TestMyTest类的新实例。注意这里假设所有的测试方法都是非静态的。

总结

通过这篇文章,我们了解了如何利用Java的注解和反射机制来模拟JUnit框架的基本工作原理。这个简单的例子展示了如何定义自定义注解、编写测试类以及创建一个模拟JUnit行为的运行器。尽管这里的实现远没有JUnit那么复杂和强大,但它确实提供了一个很好的学习平台,帮助开发者理解底层的工作机制。对于想要深入理解Java语言特性和单元测试概念的人来说,这无疑是一次有益的实践。

标签:自定义,MyTest,JUnit,注解,annotation,public,测试方法
From: https://www.cnblogs.com/itcq1024/p/18588965

相关文章

  • 深入理解 @Target 和 @Retention 注解
    深入理解@Target和@Retention注解在Java中,注解是一种元数据,为代码提供额外信息。在自定义注解时,@Target和@Retention是两个非常重要的元注解,它们用于控制注解的适用范围和生命周期。本文将详细介绍这两个注解的作用,尤其是在下面这个示例中的使用场景:@Target(ElementTyp......
  • 深入解析Java注解机制:获取注解数据的原理
    深入解析Java注解机制:获取注解数据的原理引言在Java编程中,注解(Annotation)是一种元数据形式,它提供了关于程序代码的数据,但它们并不是程序本身的一部分。注解可以用于编译时或运行时处理,以提供额外的信息或者影响程序行为。本文将深入探讨如何解析Java中的注解,并介绍AnnotatedElem......
  • ​‌Spring Boot中的@GetMapping注解可以用于处理HTTP GET请求,并且可以接收对象参数​
    下面内容来自Ai回答,经过亲自验证,正确 ‌SpringBoot中的@GetMapping注解可以用于处理HTTPGET请求,并且可以接收对象参数。‌接收对象参数的基本方式在SpringBoot中,可以通过@GetMapping注解接收对象参数,这通常通过@RequestParam或@RequestBody注解来实现。‌使用@Reque......
  • 深入理解Java注解Annotation:从基础到实战
    深入理解Java注解Annotation:从基础到实战引言Java注解(Annotation)是JDK1.5引入的一个强大特性,它允许开发者在代码中添加元数据(metadata),这些元数据可以在编译时、类加载时或运行时被读取和处理。注解不仅简化了代码的配置和维护,还为框架和工具提供了丰富的扩展点。本文将详细介绍......
  • uniapp图片懒加载全局自定义指令
    UniApp图片懒加载在UniApp中,<image>组件的图片渲染策略是通过子元素div背景图(background-image)来进行处理,而不是直接修改src。全局自定义指令constlazyDirective={mounted(el,binding){constpic_src=binding.valueconstobServer=newI......
  • 写一个方法实现自定义右键菜单的功能
    functioncreateCustomContextMenu(menuItems){//隐藏浏览器默认右键菜单document.addEventListener('contextmenu',(event)=>{event.preventDefault();});//创建自定义菜单元素constcontextMenu=document.createElement('div');contextM......
  • Qt编写嵌入式linux输入法/支持自定义词语和繁体/支持wayland和watson/纯QWidget/界面
    一、功能特点纯QWidget编写,原创输入法机制,没有任何第三方动态库的依赖。支持各种Qt版本,包括Qt4、Qt5、Qt6及后续版本。支持各种编译器,包括mingw、msvc、gcc、clang、wasm等。支持各种目标平台,包括windows、linux、macos、android、嵌入式linux等。支持任意控件输入,包括文本......
  • 使用自定义 MSBuild Task 阻止 git 的大文件提交
    NuGetGallery|Jgrass.MSBuild.GitTask前言在.NET项目自定义MSBuildTask中提到,可以使用自定义MSBuildTask来实现自定义功能。这里介绍实现的git提交大文件提交拦截功能。引入nuget包之后,设置好要拦截的大小,内置的LargeFileInterceptTask会自动在当前仓库写入......
  • Element-Plus表格:Table自定义合并行数据的最佳实践
    Element-Plus表格:Table自定义合并行数据的最佳实践“知行合一”——王阳明在开发项目中,我们时常会用到表格,许多需求可能会要求自定义特定的行或列。 接下来,我们将探讨在实际开发中如何应对这一挑战。本文案例采用的技术:名称版本Vue3^3.5.12element-plus^2.8.8......
  • 使用注解@ExcelIgnoreUnannotated实现了在导出 Excel 时忽略没有被标注的字段
    @ExcelIgnoreUnannotated注解用于在使用ApachePOI或其他Excel处理库时,指示在导出Excel时忽略没有被标注的字段。这意味着只有被特定注解(如@ExcelProperty)标注的字段会被处理和导出。作用简化导出过程:只导出需要的字段,避免不必要的数据被写入Excel文件。提高可读性:使导......