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

news/2024/11/13 15:50:39/

LoggerFactory 简介

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

<a class=LoggerFactory 代码结构" height="237" src="https://i-blog.csdnimg.cn/direct/4172b0a77b4a4da9a571b962012502c6.png" width="505" />
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.ppmy.cn/news/1545835.html

相关文章

关于 AJAX 与 Promise

AJAX (Asynchronous JavaScript and XML) AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一种在网页上异步传输数据的技术&#xff0c;允许网页在不重新加载整个页面的情况下更新部分内容。这提高了用户的体验&#xff0c;因为用户不需要等待整个页面重新加载…

DocuBurst——基于java实现

DocuBurst 文档散(DocuBurst)也是基于关键词的文本可视化,不过它还通过径向布局体现了词的语义等级。如下图所示,外层的词是内层词的下义祠,颜色饱和度的深浅用来体现词频的高低。 DocuBurst 是第一个利用词法数据库中人工创建的结构的文档内容可视化。我们使用公认的设…

如何在 Android 上增加 SELinux 权限

SELinux&#xff08;Security-Enhanced Linux&#xff09;是一种强制访问控制&#xff08;MAC&#xff09;机制&#xff0c;它为 Android 系统提供了额外的安全层。通过 SELinux&#xff0c;系统管理员可以定义细粒度的安全策略&#xff0c;限制进程对文件、网络和其他资源的访…

智能出行助手:SpringBoot共享汽车管理平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理共享汽车管理系统的相关信息成为必然。开发…

从个人品牌到企业品牌:开源 AI 智能名片 S2B2C 商城小程序的启示

摘要&#xff1a;本文探讨了个人品牌与企业品牌在信任天花板、可持续性等方面的差异&#xff0c;并引入开源 AI 智能名片 S2B2C 商城小程序作为案例&#xff0c;分析其在品牌构建过程中如何突破个人品牌的局限&#xff0c;融合品牌域和人格域&#xff0c;实现商业价值的提升和持…

AI时代IDE解析

AI时代&#xff1a;新一代IDE智能特性解析 &#x1f916; 随着人工智能技术的快速发展&#xff0c;现代集成开发环境(IDE)正在经历前所未有的变革。接下来咱们一起深入探讨AI驱动的IDE新特性&#xff0c;帮助自己提升编程效率和代码质量。 第一部分&#xff1a;AI辅助编码功能解…

在 Java 中使用脚本语言

在 Java 中使用脚本语言&#xff0c;特别是在 Java 平台上集成如 Python、JavaScript 或 Ruby 等语言&#xff0c;通常可以通过 Java 的 Scripting API 来实现。这个 API 基于 JSR 223&#xff08;“Scripting for the Java Platform”&#xff09;&#xff0c;提供了一种标准方…

大语言模型切分多头的多设备协同计算研究

目录 大语言模型切分多头的多设备协同计算研究 大语言模型切分多头的多设备协同计算研究 摘要: 随着物联网技术的不断进步,多移动终端设备的数据感知与计算需求日益激增。传统云端集中计算模式面临着高数据传输成本和不稳定网络等问题,直接影响智能物联网应用的可靠性和响…