Java 单元测试_JUnit 框架

2023-10-29

1. 单元测试简介

单元测试就是针对最小的功能单元编写测试代码。Java程序最小的功能单元是方法,因此,对Java程序进行单元测试就是针对单个Java方法的测试。

1.1. JUnit

JUnit 是一套测试框架,JUnit是一个开源的Java语言的单元测试框架,专门针对Java设计。
最近版本是 Junit 5。

2. 如何使用 JUnit 编写单元测试

2.1. 项目目录结构

在这里插入图片描述

2.2. 自动生成测试类

IntelliJ IDE 里面已经集成了 Junit 库,可以直接引用,方法如下:
1.在要生成测试类的类里面,按ctrl+shift+t –> create new test
这里选择的是 JUnit4 的库,4 和 5 的规则稍有不同,下面的讲解都以JUnit4为主
在这里插入图片描述

2.3. 编写测试代码

2.3.1. TestCase 之前的准备工作

JUnit 4 很多规则都是使用注解来完成,比如:

  • @Before:会在每一个测试方法被运行前执行一次;一般会做初始化的工作
  • @After:会在每一个测试方法运行后被执行一次;做一些清除工作,避免影响到下一条测试用例
public class SensorsTest {

    public SensorsTest() throws IOException, InvalidArgumentException {
    }//execute for each test, before executing test
    @Before
    public void before() throws NoSuchFieldException, IllegalAccessException {
        System.out.println("in before");
        final ISensorsABTest abTest = new SensorsABTest(abGlobalConfig);
        ExperimentCacheManager cacheManager =
                getExperimentCacheManagerByReflect(getSensorsABTestWorkerByReflect(abTest));
        getExperimentResultCacheByReflect(cacheManager).invalidateAll(); //强制清除实验缓存

        EventCacheManager eventCacheManager =
                getEventCacheManagerByReflect(getSensorsABTestWorkerByReflect(abTest));

        getEventCacheByReflect(eventCacheManager).invalidateAll(); //强制清除事件缓存

    }

    //execute for each test, after executing test
    @After
    public void after() {
         System.out.println("in after");
    }
        

相似的注解还有
@BeforeClass: 会在所有的方法执行前被执行,static 方法 (全局只会执行一次,而且是第一个运行)
@AfterClass:会在所有的方法执行之后进行执行,static 方法 (全局只会执行一次,而且是最后一个运行)
2.3.2. TestCase 编写
使用注解 @Test 修饰一个TestCase,
测试方法必须使用 public void 进行修饰,不能带参数
@Test(timeout=毫秒数),表示方法的超时时间,如果超时会报错

    /**
     * 立即调用,返回试验JSON类型,SDK JSON类型为JSON 字符串类型。
     */
    @Test
    public void asyncFetchABTestReturnRightResult() throws IOException, InvalidArgumentException {

        //初始化 AB Testing SDK
        final ISensorsABTest abTest = new SensorsABTest(abGlobalConfig);
//        Experiment<String> result = abTest.asyncFetchABTest(distinctId, false, experimentName, "{\"color\":\"grey\"}");
        Experiment<Integer> result = abTest.asyncFetchABTest(distinctId, false, experimentName, -1);
        System.out.println(" ========== " + result.getResult());
        assertNotNull(result);
        assertNotNull(result.getDistinctId());
        assertNotNull(result.getIsLoginId());
        assertNotNull(result.getResult());
        assertTrue(result.getResult() != null);
    }

其中,我们使用断言 assertXXX 方法来判断执行结果是否正确,断言法法如下:
编号 断言
1 void assertEquals(boolean expected, boolean actual)
检查两个变量或者等式是否平衡
2 void assertTrue(boolean condition)
检查条件为真
3 void assertFalse(boolean condition)
检查条件为假
4 void assertNotNull(Object object)
检查对象不为空
5 void assertNull(Object object)
检查对象为空
6 void assertSame(Object expected, Object actual)
assertSame() 方法检查两个相关对象是否指向同一个对象
7 void assertNotSame(Object expected, Object actual)
assertNotSame() 方法检查两个相关对象是否不指向同一个对象
8 void assertArrayEquals(expectedArray, resultArray)
assertArrayEquals() 方法检查两个数组是否相等

2.4. 测试执行
在 IntelliJ 中可以直接测试执行单个的 TestCase,如下:
在这里插入图片描述

或者执行所有的测试方法:
在这里插入图片描述

测试结果如下:
在这里插入图片描述

3. Java A/B Testing 测试 Tips

3.1. 接口超时测试方法

SDK-3100 - 【Java A/B Testing SDK 自定义属性】timeout_设置为-1或者0,应该取默认值 3s 完成
操作步骤:
1.调用 AsyncFetchABTest 接口
2.传入必填参数
3.设置弱网(Charles 对 测试Demo的请求设置断点 )
4.超时参数输入0
5.

// Java 测试代码
ABGlobalConfig abGlobalConfig = ABGlobalConfig.builder().setSensorsAnalytics(sa).setApiUrl("http://localhost:8887/timeoutTest").build();
ISensorsABTest sensorsABTest = new SensorsABTest(abGlobalConfig);
int timeout = 0
Map<String, Object> customProperties = Maps.newHashMap();
customProperties.put("age", 15);
Long start = System.currentTimeMillis();
Experiment<String> experiment =
        sensorsABTest.asyncFetchABTest("123", true, "fz",
                "eee", timeout, customProperties);
Long end = System.currentTimeMillis();
log.info(getTimeStamp(end-start) + "实验结果" + experiment.getResult());
assertNotNull(experiment);
assertNotNull(experiment.getAbTestExperimentId());
assertEquals(3000, end-start, 100);

在这里插入图片描述

3.1.1. 注意:直接配置 IntellJ 的代理 依然是无法用 Charles 抓到请求包,所以需要把 ab的请求地址定向到本地 “http://localhost:8887/timeoutTest”
在这里插入图片描述

3.2. 自动验证事件中的字段
方法一:通过反射机制拿到 BatchConsumer 中的 messageList 值

@Before
public void init() throws NoSuchFieldException, IllegalAccessException {
    String url = "http://10.120.73.51:8106/sa?project=default&token=";
    // 注意要设置 bulkSize 稍微大一点,这里设置为 100,否则超过 1 条就上报,messageList 里面拿不到事件数据
    batchConsumer = new BatchConsumer(url, 100, true, 3);
    // 通过反射机制获取 BatchConsumer 的 messageList
    Field field = batchConsumer.getClass().getDeclaredField("messageList");
    field.setAccessible(true);
    messageList = (List<Map<String, Object>>) field.get(batchConsumer); // messageList 是 BatchConsumer 用来暂存事件数据的成员变量
    saTmp = new SensorsAnalytics(batchConsumer);
}

private void assertNotNullProp(){
    assertNotNull(messageList.get(0).get("identities"));
    assertNotNull(messageList.get(0).get("time"));
    assertNotNull(messageList.get(0).get("_track_id"));
    assertNotNull(messageList.get(0).get("properties"));
    assertNotNull(messageList.get(0).get("project"));
    assertNotNull(messageList.get(0).get("token"));
}

    Map<String, Object> props = (Map<String, Object>)messageList.get(0).get("properties");
    Boolean isLoginID = (Boolean)props.get("$is_login_id");
    assertTrue(isLoginID);

方法二:通过反射机制拿到 ConcurrentLoggingConsumer 中的私有成员变量 messageBuffer 值

  consumer = new ConcurrentLoggingConsumer("file.log");
  sa = new SensorsAnalytics(consumer);
  Field field = consumer.getClass().getSuperclass().getDeclaredField("messageBuffer");
  field.setAccessible(true);
  messageBuffer = (StringBuilder) field.get(consumer);

assertNotNull(messageBuffer);
assertNotEquals(0, messageBuffer.length());
JsonNode eventJsonNode = SensorsAnalyticsUtil.getJsonObjectMapper().readValue(messageBuffer.toString(), JsonNode.class);
// 检查事件的属性值
assertEquals("$ABTestTrigger", eventJsonNode.findValue("event").asText());
assertEquals("a123", eventJsonNode.findValue("distinct_id").asText());
assertEquals(2, eventJsonNode.get("properties").findValue("$abtest_experiment_id").asInt());
assertEquals(1, eventJsonNode.get("properties").findValue("$abtest_experiment_group_id").asInt());

【SensorsAnalyticsUtil.java】

 public static ObjectMapper getJsonObjectMapper() {
    ObjectMapper jsonObjectMapper = new ObjectMapper();
    jsonObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    jsonObjectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
    jsonObjectMapper.setTimeZone(TimeZone.getDefault());
    jsonObjectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
    return jsonObjectMapper;
} 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 单元测试_JUnit 框架 的相关文章

  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 我可以使用 HSQLDB 进行 junit 测试克隆 mySQL 数据库吗

    我正在开发一个 spring webflow 项目 我想我可以使用 HSQLDB 而不是 mysql 进行 junit 测试吗 如何将我的 mysql 数据库克隆到 HSQLDB 如果您使用 spring 3 1 或更高版本 您可以使用 s
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • 机器学习(Machine Learning)&深度学习(Deep Learning)资料

    机器学习 Machine Learning 深度学习 Deep Learning 资料 Chapter 1 注 机器学习资料 篇目一 https github com ty4z2008 Qix blob master dl md 共500条
  • linux中主线程退出后子线程的状态

    1 运行如下代码 即是简单创建一个子线程 主线程直接结束 然后在子线程中每间隔一秒就打印一个HELLO 利用ps ef查看进程状态 发现没有主线程和子线程都不在 即是主线程退出后子线程也会退出 2 运行如下代码 增加利用pthread ex
  • js动态添加与删除ul中的li

    方法一 createElement li 方式方法二 innerHTML方式方法一实例 参考 http zhidao baidu com question 175951279 html
  • 2021-02-05

    一个 C 转 GO 的程序员的自白 GO 一个文件下载过滤需求 var file been found lock sync Mutex var file been found map string int make map string i
  • 我的 PhpStorm 设置

    可能因为 PhpStorm 版本不同的原因 你找不到如下设置的地点 此时可以在设置界面搜索设置项的关键字 软件字体 进入设置 Settings gt Appearance Behavior gt Appearance 勾选Override
  • 华为OD机试真题 Java 实现【报数游戏】【2022Q4 100分】

    一 题目描述 100个人围成一圈 每个人有一个编码 编号从1开始到100 他们从1开始依次报数 报到为M的人自动退出圈圈 然后下一个人接着从1开始报数 直到剩余的人数小于M 请问最后剩余的人在原先的编号为多少 二 输入描述 输入一个整数参数
  • SQL基本的表修改及其它命令

    对于已经建好的表 有时可能因为业务的变动或者设计时考虑的不周全而需要进行列的调整 包 括增加一个新的列 修改一个列 为列定义一个缺省值 删除一个列等 对应语句语法分别如下 ALTER TABLE table ADD column datat
  • pytorch中一维卷积conv1d,参数含义,为何转置

    pytorch中一维卷积conv1d 参数含义 为何转置 在Pytorch中 一维卷积是一种非常常用的运算 但是对于刚刚入门的新手 了解此函数的用法仍是一个比较费力的挑战 本文简单介绍一下此函数的常用参数的意义以及此函数的用法 链接 cov
  • Node.js 利用高阶函数 ( 柯里化 ) 并发写入流、读取流(Stream)

    首先 介绍Stream实例对象的方法 data 读数据时触发 end 数据读取完毕时触发 error 在接收和写入过程中发生错误时触发 finish 所有数据已被写入到底层系统时触发 今天 我们利用node对stream对象的支持 利用高阶
  • 在Windows下使用Anaconda安装TesnsorFlow 2.x

    作者 弗拉德 来源 弗拉德 公众号 fulade me 下载 Anaconda 首先打开Anaconda官网找到网页底部 由于最新的Anaconda支持Python3 8版本 而TesnorFlow最高支持到Python3 7 我特意查了一
  • java.lang.IllegalStateException: Failed to load ApplicationContext

    问题描述 mvn clean install的时候报的如下异常 紧接着又往下翻了一下日志还有一个这个错误 按正常来说通过 可以取pom当中的properties标签的值呀 但是可以发现编译过后的application当中的值并没有被替换 解
  • 2022年最新版黑马程序员Java学习路线

    工欲善其事 必先利其器 自学Java的同学 必备的自学五部曲 学习路线图 学习教程 工具 书籍 面试 一 Java学习路线图 学习路线图说明 二 学习教程推荐 阶段一Java基础 具备Java语言编程基础和IO 多线程 网络编程等开发能力
  • Zstack 挂载云盘,在Windows下面看不到解决方法

    原因 在使用 Zstack 私有云时 创建 WinServer2019 时 想添加一块数据云盘 但是添加好后 进入系统看不到硬盘 主要是因为添加的云盘驱动是 virtio 格式 所以要安装相关驱动 1 查看挂载的云盘 root zstack
  • 【避坑】minio临时凭证STS实现上传,下载

    一 背景 以minio作为图床 采用用户到minio服务器的点对点使用方式 将上传用户的长期凭证放在客户端 app或者web端 带来极大的风险 通常通过临时凭证STS签名的方式实现 简单的逻辑关系图如下 二 minio服务docker安装
  • Android仿小米商城底部导航栏之二(BottomNavigationBar、ViewPager和Fragment的联动使用)

    简介 在前文 Android仿小米商城底部导航栏 基于BottomNavigationBar 我们使用BottomNavigationBar控件模仿实现了小米商城底部导航栏效果 接下来更进一步的 我们将通过BottomNavigationB
  • Python之爬虫总结

    一 爬虫之requests a 介绍 使用requests可以模拟浏览器的请求 比起之前用到的urllib requests模块的api更加便捷 本质就是封装了urllib3 b 注意 requests发送请求是将网页内容下载来以后 并不会
  • CRMEB Pro版多店版v2.5更新分享

    CRMEB Pro版 v2 4正式发布啦 Pro版系统性能再度提升 并发量可达3w 另外 新增商品设置 积分 金额兑换 订单管理 营销风格 活动背景 活动边框 应用配置引导弹窗等众多新功能 系统升级 1 性能提升 Pro版系统性能再度提升
  • hbase小版本升级

    备份原版本 cd opt hbase cp pr bin bin bak cp pr lib lib bak cp pr hbase webapps hbase webapps bak 停止hbase opt hbase bin stop
  • 前端报403错误的可能原因

    1 跨域问题 2 请求服务器路径问题
  • Java 单元测试_JUnit 框架

    1 单元测试简介 单元测试就是针对最小的功能单元编写测试代码 Java程序最小的功能单元是方法 因此 对Java程序进行单元测试就是针对单个Java方法的测试 1 1 JUnit JUnit 是一套测试框架 JUnit是一个开源的Java语