单元测试日志打印相关接口及类 Logger

LoggerFactory 简介

单元测试常用日志打印工具LoggerFactory。

LoggerFactory 代码结构
LoggerFactory 代码结构

LoggerFactory 是 JUnit 平台中的一个类,用于创建 Logger 实例。它被设计用于提供日志记录功能,使得 JUnit 在执行测试时能够记录信息、警告、错误等。

LoggerFactory 的主要目的是为 JUnit 提供一个集中式的日志记录机制,允许在测试过程中记录重要的信息,同时保持与不同日志实现的灵活性。这样做可以增强调试能力和监控测试执行过程中的重要事件。

package org.junit.platform.commons.logging;/*** Factory for the {@link Logger} facade for JUL.** @since 1.0*/
@API(status = INTERNAL, since = "1.0")
public final class LoggerFactory {private LoggerFactory() {/* no-op */}private static final Set<LogRecordListener> listeners = ConcurrentHashMap.newKeySet();private static final class DelegatingLogger implements Logger {}}

创建 Logger 实例(示例)

 LoggerFactory 的主要职责是根据传入的参数创建适当的 Logger 实例。这个实例可以用于记录不同级别的日志,例如调试信息、错误信息等。

	/*** Get a {@link Logger} for the specified class.** @param clazz the class for which to get the logger; never {@code null}* @return the logger*/public static Logger getLogger(Class<?> clazz) {// NOTE: we cannot use org.junit.platform.commons.util.Preconditions here// since that would introduce a package cycle.if (clazz == null) {throw new JUnitException("Class must not be null");}return new DelegatingLogger(clazz.getName());}

调用方式:

public class Test {private Logger logger = LoggerFactory.getLogger(this.getClass());
}

使用原生的Logger有个问题就是,日志打印的时候传入的参数对象不合适,需要自己再封装,愿意如下,看Logger 接口的定义。

Logger 接口

package org.junit.platform.commons.logging;/*** The {@code Logger} API serves as a simple logging facade for* {@code java.util.logging} (JUL).** @since 1.0*/
@API(status = INTERNAL, since = "1.0")
public interface Logger {/*** Log the provided {@code Throwable} and message from the provided* {@code messageSupplier} at error level.** <p>Maps to {@link java.util.logging.Level#SEVERE} in JUL.*/void error(Throwable throwable, Supplier<String> messageSupplier);/*** Log the provided {@code Throwable} and message from the provided* {@code messageSupplier} at info level.** <p>Maps to {@link java.util.logging.Level#INFO} in JUL.*/void info(Throwable throwable, Supplier<String> messageSupplier);/*** Log the provided {@code Throwable} and message from the provided* {@code messageSupplier} at trace level.** <p>Maps to {@link java.util.logging.Level#FINER} in JUL.*/void trace(Throwable throwable, Supplier<String> messageSupplier);}

自定义Logger

因为库函数中的日志工具比较抽象,所以自定义Logger是很关键的。

一个保存数据时验证UI行为的功能。

import org.junit.platform.commons.logging.LoggerFactory;/**
* 保存数据,验证是否弹窗的功能
*/@RunWith(MockitoJUnitRunner.class)    
public class TestSave {private static final String TAG = "TestSave";//内部自定义日志打印接口,没使用库的类就要自己定义接口@Mockprivate Logger logger;  // Mocking the Logger class used for Log.d statements@Mockprivate SaveActivity activity;// Instance of the class to test, initialised in setUpprivate SaveActivityUnderTest saveActivityUnderTest;//过程空值变量,类似flag的作用// Helper mock boolean variables to control the test casesprivate boolean mIsShowSaveDialog;private boolean mIsApnListChanged;@Beforepublic void setUp() {saveActivityUnderTest = new SaveActivityUnderTest();saveActivityUnderTest .logger = logger;saveActivityUnderTest .activity = activity;}// Moved the class outside any other class scope to avoid issues with instantiationstatic class SaveActivityUnderTest {private Logger logger;private SaveActivity activity;public void onMenuSave() {logger.info(TAG, "MENU_SAVE: mIsShowSaveDialog = " + mIsShowSaveDialog);if (mIsShowSaveApnDialog) {if (mIsListChanged) {activity.showSaveDialog();} else {activity.finish();}} else {if (activity.validateAndSaveData()) {activity.finish();}}}}//省略测试代码//自定义接口,这是还没有实现的。private interface Logger {void d(String tag, String message);void info(String tag, String message);void error(String message);void warn(String message);}private interface SaveActivity {boolean validateAndSaveData();void showSaveDialog();void finish();}}

参考源码库定制适合自己类的log。

LoggerFactory 常量类

final class 不能被继承。

package com.demo.test.util;import org.junit.platform.commons.JUnitException;import java.util.logging.Level;
import java.util.logging.LogRecord;public final class LoggerFactory {private LoggerFactory() {/* no-op */}public static Logger getLogger(Class<?> clazz) {// NOTE: we cannot use org.junit.platform.commons.util.Preconditions here// since that would introduce a package cycle.if (clazz == null) {throw new JUnitException("Class must not be null");}return new TestLogger(clazz.getName());}private static final class TestLogger implements Logger {private static final String FQCN = TestLogger.class.getName();private final String name;private final java.util.logging.Logger julLogger;TestLogger(String name) {this.name = name;this.julLogger = java.util.logging.Logger.getLogger(this.name);}@Overridepublic void error(String tag, String message) {System.out.println(tag + ": " + message);}@Overridepublic void warn(String tag, String message) {}@Overridepublic void info(String message) {log(Level.INFO, null, message);}@Overridepublic void info(Throwable throwable, String message) {log(Level.INFO, throwable, message);}@Overridepublic void info(String tag, String message) {System.out.println(tag + ": " + message);}@Overridepublic void config(String tag, String message) {}@Overridepublic void debug(String tag, String message) {}@Overridepublic void trace(String tag, String message) {}private void log(Level level, Throwable throwable, String msg) {boolean loggable = this.julLogger.isLoggable(level);if (loggable) {LogRecord logRecord = createLogRecord(level, throwable, msg);}}private LogRecord createLogRecord(Level level, Throwable throwable, String message) {String sourceClassName = null;String sourceMethodName = null;boolean found = false;for (StackTraceElement element : new Throwable().getStackTrace()) {String className = element.getClassName();if (FQCN.equals(className)) {found = true;}else if (found) {sourceClassName = className;sourceMethodName = element.getMethodName();break;}}LogRecord logRecord = new LogRecord(level, message);logRecord.setLoggerName(this.name);logRecord.setThrown(throwable);logRecord.setSourceClassName(sourceClassName);logRecord.setSourceMethodName(sourceMethodName);logRecord.setResourceBundleName(this.julLogger.getResourceBundleName());logRecord.setResourceBundle(this.julLogger.getResourceBundle());return logRecord;}}}

Logger接口

package com.demo.test.util;public interface Logger {void error(String tag, String message);void warn(String tag, String message);void info(String message);void info(Throwable throwable, String message);void info(String tag, String message);void config(String tag, String message);void debug(String tag, String message);void trace(String tag, String message);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/465954.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【万字总结】数据结构常考应用大题做法画法详解_树_哈希表_图_排序大总结

文章目录 1.树相关应用大题1.1 已知二叉树的中序序列和前序or中序&#xff0c;画出二叉树1.2 二叉树的遍历、树的遍历、森林的遍历总结1.3二叉树与森林之间的转换1.3.1 已知树的先序序列和中序序列&#xff0c;画出森林 1.4 二叉树的线索化1.5 二叉排序树1.5.1 二叉排序树的删除…

越权访问漏洞

V2Board Admin.php 越权访问漏洞 ## 漏洞描述 V2board面板 Admin.php 存在越权访问漏洞&#xff0c;由于部分鉴权代码于v1.6.1版本进行了修改&#xff0c;鉴权方式变为从Redis中获取缓存判定是否存在可以调用… V2Board Admin.php 越权访问漏洞 漏洞描述 V2board面板 Admin.ph…

接口测试用例设计的关键步骤与技巧解析!

简介 接口测试在需求分析完成之后&#xff0c;即可设计对应的接口测试用例&#xff0c;然后根据用例进行接口测试。接口测试用例的设计也需要用到黑盒测试用例设计方法&#xff0c;和测试流程与理论章节的功能测试用例设计的方法类似&#xff0c;设计过程中还需要增加与接口特…

Redis常见面试题(二)

Redis性能优化 Redis性能测试 阿里Redis性能优化 使用批量操作减少网络传输 Redis命令执行步骤&#xff1a;1、发送命令&#xff1b;2、命令排队&#xff1b;3、命令执行&#xff1b;4、返回结果。其中 1 与 4 消耗时间 --> Round Trip Time&#xff08;RTT&#xff0c;…

功能超全的客服快捷回复软件

客服日常工作繁忙&#xff0c;需要一款满足各项日常需求的客服工具&#xff0c;完成咨询的快捷回复&#xff0c;并能共享客服团队优质话术&#xff0c;实现云端文件储存&#xff0c;管理表情动图等功能 前言 客服日常工作繁忙&#xff0c;需要一款满足各项日常需求的客服工具。…

靠Python真的能实现经济自由,学会了你也可以

不知道大家有没有注意到&#xff0c;最近关注的很多人都在聊“副业and兼职”这件事。 毕竟单一收入已经不能满足现代人的需求了。 对于普通人来说&#xff0c;想要跳出固定思维和舒适圈&#xff0c;相比于孤注一掷的创业&#xff0c;更推荐兼职。 很多人想要创业&#xff0c;…

【案例分享】借助 iSpring,创造客户真正欣赏的专业在线培训体验

Safety Bee Training是一家领先的认证在线学习提供商&#xff0c;专门提供职业健康、安全和环境项目。它也是中东和亚洲唯一一家提供经 NASP 等国际认证机构认可的课程的培训提供商。它已经培训了超过 28,000 名学习者&#xff0c;并且正在不断扩大其课程范围&#xff0c;以提供…

IP可用端口扫描器工具(bun + typescript)

IP可用端口扫描器工具&#xff08;bun typescript&#xff09; 学习方式&#xff1a;源码学习。通过项目和源码可以学习到如下内容&#xff1a;1、bun搭建项目&#xff0c;打包项目2、net、dns等node内置模块的使用3、yargs、assert、progress、cli-color等三方包的使用ps&am…

docker镜像仓库常用命令

docker镜像仓库常用命令 docker logindocker logoutdocker pulldocker pushdocker searchdocker imagesdocker image inspectdocker tagdocker rmidocker image prunedocker savedocker loaddocker history docker login 语法: docker login [options] [server] 功能&#xff…

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的&#xff0c;对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务&#xff0c;但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…

外包干了2年,快要废了。。。

先说一下自己的情况&#xff0c;普通本科&#xff0c;在外包干了2年多的功能测试&#xff0c;这几年因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不能够在这样蹉跎下去了&#xff0c;长时间呆在一个舒适的环境真的会让一…

【青牛科技】GC8549替代LV8549/ONSEMI在摇头机、舞台灯、打印机和白色家电等产品上的应用分析

引言 在现代电子产品中&#xff0c;控制芯片的性能直接影响到设备的功能和用户体验。摇头机、舞台灯、打印机和白色家电等领域对控制精度、功耗和成本等方面的要求日益提高。LV8549/ONSEMI等国际品牌的芯片曾是这些产品的主要选择&#xff0c;但随着国内半导体技术的进步&…

Spring挖掘:(AOP篇)

学习AOP时,我们首先来了解一下何为AOP 一. 概念 AOP&#xff08;面向切面编程&#xff0c;Aspect Oriented Programming&#xff09;是一种编程技术&#xff0c;旨在通过预编译方式或运行期动态代理实现程序功能的统一管理和增强。AOP的主要目标是在不改变原有业务逻辑代码的…

Centos Linux 7 搭建邮件服务器(postfix + dovecot)

准备工作 1. 一台公网服务器&#xff08;需要不被服务商限制发件收件的&#xff0c;也就是端口25、110、143、465、587、993、995不被限制&#xff09;&#xff0c;如有防火墙或安全组需要把这些端口开放 2. 一个域名&#xff0c;最好是com cn org的一级域名 3. 域名备案&am…

深入了解Bootstrap框架:从入门到精通

文章目录 前言Bootstrap的核心特性1. 响应式设计2. 丰富的组件库3. 易于使用4. 良好的兼容性 安装与使用安装1. 通过CDN引入2. 下载源码3. 使用npm或yarn 基本使用1. 栅格系统2. 按钮3. 导航条4. 卡片5. 模态框6. 轮播图7. 表单 高级定制1. 修改 Sass 变量2. 按需引入组件 最佳…

ENSP RIP动态路由

RIP&#xff08;距离矢量路由协议&#xff09;以网络中所有链路的距离和矢量为依据计算最佳路径&#xff0c;是第一个动态路由协议。条数作为唯一的度量单位。默认开启水平分割&#xff08;从一个路由接口学到的路由信息&#xff0c;便不在从这个接口发送出去&#xff09;防止路…

华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)

华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目分享——共九套&#xff08;每套四十题&#xff09; 岗位——芯片与器件设计工程师 岗位意向——模拟芯片 真题题目分享&#xff0c;完整题目&#xff0c;无答案&#xff08;共8套&#xff09; 实习岗位…

MySQL45讲 第十一讲 怎么给字符串字段加索引?

文章目录 MySQL45讲 第十一讲 怎么给字符串字段加索引&#xff1f;一、引言二、前缀索引&#xff08;一&#xff09;概念与创建方式&#xff08;二&#xff09;数据结构与存储差异&#xff08;三&#xff09;确定前缀长度的方法 三、前缀索引对覆盖索引的影响四、其他索引创建方…

字节青训-小S的倒排索引

问题描述 小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子&#xff0c;小S决定使用倒排索引。倒排索引的工作原理是&#xff1a;每个单词都会关联一个帖子ID的列表&#xff0c;这些帖子包含该单词&#xff0c;且ID按从小到大的顺序排列。 例…

讲讲分布式与集群的区别?

大家好&#xff0c;我是锋哥。今天分享关于【讲讲分布式与集群的区别&#xff1f;】面试题。希望对大家有帮助&#xff1b; 讲讲分布式与集群的区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在现代计算和信息技术领域&#xff0c;分布式系统和集…