赞
踩
Junit是一个开源的 Java 单元测试框架。
单元测试,就是针对最小的功能单元编写测试代码。在 Java 中,最小的功能单元就是方法,因此,对 Java 程序员进行单元测试实际上就是对 Java 方法的测试。
单元测试可以确保你编写的代码是符合软件需求和遵循开发规范的。单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次能够达到代码覆盖率 100% 的测试,是整个软件测试过程的基础和前提。
1.导入依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
2.测试方法中添加一组断言(假设有一个Factorial类且有待测方法fact)
@Test
void fact() {
assertEquals(1, Factorial.fact(1));
assertEquals(2, Factorial.fact(2));
assertEquals(6, Factorial.fact(3));
assertEquals(100, Factorial.fact(5));
}
3.右键点「Run FactorialTest」,即可得到哪一行执行失败。
测试也支持添加前后逻辑:@BeforeEach、@AfterEach、@BeforeAll、@AfterAll
class CalculatorTest { Calculator calculator; @BeforeEach void setUp() { calculator = new Calculator(); } @AfterEach void tearDown() { calculator = null; } @Test void sub() { assertEquals(0,calculator.sub(1,1)); } @Test void add() { assertEquals(2,calculator.add(1,1)); } }
@BeforeEach
的 setUp()
方法会在运行每个 @Test
方法之前运行;
@AfterEach
的 tearDown()
方法会在运行每个 @Test
方法之后运行。
public class DatabaseTest {
static Database db;
@BeforeAll
public static void init() {
db = createDb(...);
}
@AfterAll
public static void drop() {
...
}
}
All 通常用来初始化和销毁静态变量。
public class Factorial {
public static long fact(long n) {
if (n < 0) {
throw new IllegalArgumentException("参数不能小于 0");
}
long r = 1;
for (long i = 1; i <= n; i++) {
r = r * i;
}
return r;
}
}
当n<0时怎么测试呢?答:assertThrows
@Test
void factIllegalArgument() {
assertThrows(IllegalArgumentException.class, new Executable() {
@Override
public void execute() throws Throwable {
Factorial.fact(-2);
}
});
}
使用 Lambda 表达式:
@Test
void factIllegalArgumentLambda() {
assertThrows(IllegalArgumentException.class, () -> {
Factorial.fact(-2);
});
}
@Disabled加在@Test注解之上
打印日志,缺点是影响性能,但是日常开发中必不可少。(刚入职时前辈告诉我尽量多打日志)
Log4j 的一个好处是,不需要重新启动 Java 程序就可以调整日志的记录级别,非常灵活。可以通过 log4j.properties 文件来配置 Log4j 的日志级别、输出环境、日志文件的记录方式。
Log4j 还是线程安全的,可以在多线程的环境下放心使用。
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制台 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 输出DEBUG 级别以上的日志到=debug.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = debug.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 输出ERROR 级别以上的日志到=error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
1)配置根 Logger,语法如下所示:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
level 就是日志的优先级,从高到低依次是 ERROR、WARN、INFO、DEBUG。如果这里定义的是 INFO,那么低级别的 DEBUG 日志信息将不会打印出来。
appenderName 就是指把日志信息输出到什么地方,可以指定多个地方,当前的配置文件中有 3 个地方,分别是 stdout、D、E。
2)配置日志输出的目的地,语法如下所示:
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueN
Log4j 提供的目的地有下面 5 种:
3)配置日志信息的格式,语法如下所示:
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.option = valueN
Log4j 提供的格式有下面 4 种:
自定义格式的参数如下所示:
method:com.itwanger.Log4jDemo.main(Log4jDemo.java:14)
第三步,写个使用 Demo:
package com.itwanger; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; /** * @author 微信搜「沉默王二」,回复关键字 PDF */ public class Log4jDemo { private static final Logger logger = LogManager.getLogger(Log4jDemo.class); public static void main(String[] args) { // 记录debug级别的信息 logger.debug("debug."); // 记录info级别的信息 logger.info("info."); // 记录error级别的信息 logger.error("error."); } }
1)获取 Logger 对象
要使用 Log4j 的话,需要先获取到 Logger 对象,它用来负责日志信息的打印。通常的格式如下所示:
private static final Logger logger = LogManager.getLogger(Log4jDemo.class);
2)打印日志
有了 Logger 对象后,就可以按照不同的优先级打印日志了。常见的有以下 4 种:
Logger.debug() ;
Logger.info() ;
Logger.warn() ;
Logger.error() ;
程序运行后会在 target 目录下生成两个文件,一个名叫 debug.log,内容如下所示:
2020-10-20 20:53:27 [ main:0 ] - [ DEBUG ] debug.
2020-10-20 20:53:27 [ main:3 ] - [ INFO ] info.
2020-10-20 20:53:27 [ main:3 ] - [ ERROR ] error.
另外一个名叫 error.log,内容如下所示:
2020-10-20 20:53:27 [ main:3 ] - [ ERROR ] error.
1)在多线程场景下,Log4j 2 的吞吐量比 Logback 高出了 10 倍,延迟降低了几个数量级。
2)Log4j 2 可以减少垃圾收集器的压力。
3)支持 Lambda 表达式。
4)支持自动重载配置。
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
(这个 artifactId 还是 log4j,没有体现出来 2,而在 version 中体现,多少叫人误以为是 log4j)
第二步,来个最简单的测试用例:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Demo {
private static final Logger logger = LogManager.getLogger(Demo.class);
public static void main(String[] args) {
logger.debug("log4j2");
}
}
**第三步,**在 resource 目录下增加 log4j2-test.xml 文件,内容如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
1)配置 appender,也就是配置日志的输出目的地。
有 Console,典型的控制台配置信息上面你也看到了,我来简单解释一下里面 pattern 的格式:
%d{HH:mm:ss.SSS}
表示输出到毫秒的时间%t
输出当前线程名称%-5level
输出日志级别,-5 表示左对齐并且固定输出 5 个字符,如果不足在右边补空格%logger
输出 logger 名称,最多 36 个字符%msg
日志文本%n
换行顺带补充一下其他常用的占位符:
%F
输出所在的类文件名,如 Demo.java%L
输出行号%M
输出所在方法名%l
输出语句所在的行数, 包括类名、方法名、文件名、行数%p
输出日志级别%c
输出包名,如果后面跟有 {length.}
参数,比如说 %c{1.}
,它将输出报名的第一个字符,如 com.itwanger
的实际报名将只输出 c.i
2)配置 Loggers,指定 Root 的日志级别,并且指定具体启用哪一个 Appenders。
3)自动重载配置。
Logback 支持自动重载配置,Log4j 2 也支持,那想要启用这个功能也非常简单,只需要在 Configuration 元素上添加 monitorInterval
属性即可。
<Configuration monitorInterval="30">
...
</Configuration>
注意值要设置成非零,上例中的意思是至少 30 秒后检查配置文件中的更改。最小间隔为 5 秒。
除了 Console,还有 Async,可以配合文件的方式来异步写入,典型的配置信息如下所示:
<Configuration> <Appenders> <File name="DebugFile" fileName="debug.log"> <PatternLayout> <Pattern>%d %p %c [%t] %m%n</Pattern> </PatternLayout> </File> <Async name="Async"> <AppenderRef ref="DebugFile"/> </Async> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Async"/> </Root> </Loggers> </Configuration>
把这个 Async 加入到 Appenders:
<Configuration> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> <File name="DebugFile" fileName="debug.log"> <PatternLayout> <Pattern>%d %p %c [%t] %m%n</Pattern> </PatternLayout> </File> <Async name="Async"> <AppenderRef ref="DebugFile"/> </Async> </Appenders> <Loggers> <Root level="DEBUG"> <AppenderRef ref="Console"/> <AppenderRef ref="Async"/> </Root> </Loggers> </Configuration>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。