笔记学习于柏码知识库
使用JUnit进行单元测试 以JUnit4为例。部分内容在JUnit5中被废弃
使用@Test注解来标记测试案例,点击测试按钮进行测试。编写的方法有以下要求:
方法必须是public的
不能是静态方法
返回值必须是void
必须是没有任何参数的方法
可以通过断言来对结果进行判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Test public void method () { int [] arr = {0 , 4 , 5 , 2 , 6 , 9 , 3 , 1 , 7 , 8 }; for (int i = 0 ; i < arr.length - 1 ; i++) { for (int j = 0 ; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1 ]){ int tmp = arr[j]; arr[j] = arr[j+1 ]; } } } Assert.assertArrayEquals(new int []{0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }, arr); }
可以使用@Before来添加前置操作:(最新版本中@Before被废弃,进行了细分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class TestMain { private SqlSessionFactory sqlSessionFactory; @Before public void before () { System.out.println("测试前置正在初始化..." ); try { sqlSessionFactory = new SqlSessionFactoryBuilder () .build(new FileInputStream ("mybatis-config.xml" )); } catch (FileNotFoundException e) { e.printStackTrace(); } System.out.println("测试初始化完成,正在开始测试案例..." ); } @Test public void method1 () { try (SqlSession sqlSession = sqlSessionFactory.openSession(true )){ TestMapper mapper = sqlSession.getMapper(TestMapper.class); Student student = mapper.getStudentBySidAndSex(1 , "男" ); Assert.assertEquals(new Student ().setName("小明" ).setSex("男" ).setSid(1 ), student); System.out.println("测试用例1通过!" ); } } @Test public void method2 () { try (SqlSession sqlSession = sqlSessionFactory.openSession(true )){ TestMapper mapper = sqlSession.getMapper(TestMapper.class); Student student = mapper.getStudentBySidAndSex(2 , "女" ); Assert.assertEquals(new Student ().setName("小红" ).setSex("女" ).setSid(2 ), student); System.out.println("测试用例2通过!" ); } } }
使用@After添加结束动作:
1 2 3 4 @After public void after () { System.out.println("测试结束,收尾工作正在进行..." ); }
Junit5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class MainTest { private static SqlSessionFactory factory; @BeforeAll @SneakyThrows public static void before () { factory = new SqlSessionFactoryBuilder () .build(Resources.getResourceAsStream("mybatis.xml" )); } @DisplayName("Mybatis数据库测试") @RepeatedTest(3) public void test () { try (SqlSession sqlSession = factory.openSession(true )){ TestMapper testMapper = sqlSession.getMapper(TestMapper.class); System.out.println(testMapper.getStudentBySid(1 )); } } }
JUL日志系统 基本介绍 简单使用:
1 2 3 4 5 6 7 8 public class Main { public static void main (String[] args) { Logger logger = Logger.getLogger(Main.class.getName()); logger.info("我是普通的日志" ); } }
日志分为7个级别。级别低于默认级别的日志信息,无法输出到控制台。可以设置自定义控制台来修改打印级别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main (String[] args) { Logger logger = Logger.getLogger(Main.class.getName()); logger.setLevel(Level.CONFIG); logger.setUseParentHandlers(false ); ConsoleHandler handler = new ConsoleHandler (); handler.setLevel(Level.CONFIG); logger.addHandler(handler); logger.log(Level.SEVERE, "严重的错误" , new IOException ("我就是错误" )); logger.log(Level.WARNING, "警告的内容" ); logger.log(Level.INFO, "普通的信息" ); logger.log(Level.CONFIG, "级别低于普通信息" ); }
也可以使用文件处理器,此时控制台和文件的日志处理器都会生效:
1 2 3 4 FileHandler fileHandler = new FileHandler ("test.log" ); fileHandler.setLevel(Level.WARNING); logger.addHandler(fileHandler);
也可以自定义样式,控制台处理器就默认使用的是SimpleFormatter,而文件处理器则是使用的XMLFormatter。
1 2 3 4 5 ConsoleHandler handler = new ConsoleHandler (); handler.setLevel(Level.CONFIG); handler.setFormatter(new XMLFormatter ()); logger.addHandler(handler);
还可以设置过滤器并配置过滤规则:
1 2 3 4 5 6 7 8 9 10 public static void main (String[] args) throws IOException { Logger logger = Logger.getLogger(Main.class.getName()); logger.setFilter(record -> !record.getMessage().contains("普通" )); logger.log(Level.SEVERE, "严重的错误" , new IOException ("我就是错误" )); logger.log(Level.WARNING, "警告的内容" ); logger.log(Level.INFO, "普通的信息" ); }
Properties文件 Properties文件配置格式:
1 2 name =Test desc =Description
可以将配置文件映射为类Map的对象:
1 2 3 4 5 public static void main (String[] args) throws IOException { Properties properties = new Properties (); properties.load(new FileInputStream ("test.properties" )); System.out.println(properties); }
日志配置文件 使用配置文件来规定日志打印器默认值:
1 2 3 4 # RootLogger 的默认处理器为 handlers= java.util.logging.ConsoleHandler # RootLogger 的默认的日志级别 .level= CONFIG
使用配置文件来进行配置:
1 2 3 4 5 6 7 8 9 public static void main (String[] args) throws IOException { LogManager manager = LogManager.getLogManager(); manager.readConfiguration(new FileInputStream ("logging.properties" )); Logger logger = Logger.getLogger(Main.class.getName()); logger.log(Level.CONFIG, "我是一条日志信息" ); }
也可以修改ConsoleHandler的默认配置:
1 2 3 4 5 6 # 指定默认日志级别 java.util.logging.ConsoleHandler.level = ALL # 指定默认日志消息格式 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter # 指定默认的字符集 java.util.logging.ConsoleHandler.encoding = UTF-8
使用Lombok快速开启日志 1 2 3 4 5 6 7 @Log public class Main { public static void main (String[] args) { System.out.println("自动生成的Logger名称:" +log.getName()); log.info("我是日志信息" ); } }
Mybatis日志系统 通过配置开启日志系统:
1 <setting name ="logImpl" value ="STDOUT_LOGGING" />
可以进一步配置日志系统,并修改格式。
修改配置文件:
1 <setting name ="logImpl" value ="JDK_LOGGING" />
格式化打印格式:
1 2 3 4 5 6 7 8 public class TestFormatter extends Formatter { @Override public String format (LogRecord record) { SimpleDateFormat format = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS" ); String time = format.format(new Date (record.getMillis())); return time + " : " + record.getMessage() + "\n" ; } }
设置logging.properties:
1 2 3 4 handlers= java.util.logging.ConsoleHandler .level= ALL java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.formatter = com.test.TestFormatter
使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Log public class TestMain { private SqlSessionFactory sqlSessionFactory; @Before public void before () { try { sqlSessionFactory = new SqlSessionFactoryBuilder () .build(new FileInputStream ("mybatis-config.xml" )); LogManager manager = LogManager.getLogManager(); manager.readConfiguration(new FileInputStream ("logging.properties" )); } catch (IOException e) { e.printStackTrace(); } } @Test public void test () { try (SqlSession sqlSession = sqlSessionFactory.openSession(true )){ TestMapper mapper = sqlSession.getMapper(TestMapper.class); log.info(mapper.getStudentBySidAndSex(1 , "男" ).toString()); log.info(mapper.getStudentBySidAndSex(1 , "男" ).toString()); } } }
Maven pom.xml文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion>4.0 .0 </modelVersion> <groupId>org.example</groupId> <artifactId>MavenTest</artifactId> <version>1.0 -SNAPSHOT</version> <properties> <maven.compiler.source>8 </maven.compiler.source> <maven.compiler.target>8 </maven.compiler.target> </properties> </project>
groupId、artifactId、version这三个元素合在一起,用于唯一区别每个项目,通过Maven导入其他的依赖只需要填写这三个基本元素就可以。
依赖导入 创建dependencies节点:
1 2 3 <dependencies > //里面填写的就是所有的依赖</dependencies >
可以在 查询依赖。以lombok为例:
1 2 3 4 5 6 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.22</version > <scope > provided</scope > </dependency >
可以在IDEA安装根目录/plugins/maven/lib/maven3/conf
文件夹,编辑settings.xml文件切换国内源。在mirros标签中添加:
1 2 3 4 5 6 <mirror > <id > nexus-aliyun</id > <mirrorOf > *</mirrorOf > <name > Nexus aliyun</name > <url > http://maven.aliyun.com/nexus/content/groups/public</url > </mirror >
依赖作用域 通过scope属性决定,包括:
compile:默认,编译、运行、测试均有效
provided:编译、测试有效,运行无效,如Lombok
runtime:在运行、测试有效,编译无效。
test:仅测试有效。如Junit。
system:本地导入,作用域与provided一样,需要添加systemPath
如导入JUnit5依赖:
1 2 3 4 5 6 <dependency > <groupId > org.junit.jupiter</groupId > <artifactId > junit-jupiter</artifactId > <version > 5.8.1</version > <scope > test</scope > </dependency >
所有的测试用例全部编写到Maven项目划分的test目录下,位于此目录下的内容不会在最后被打包到项目中,只用作开发阶段测试使用。
Maven还提供了一个resource文件夹,可以将一些静态资源,比如配置文件,放入到这个文件夹中,项目在打包时会将资源文件夹中文件一起打包的Jar中。如Mybatis配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="cacheEnabled" value ="true" /> <setting name ="logImpl" value ="JDK_LOGGING" /> </settings > <typeAliases > <package name ="com.test.entity" /> </typeAliases > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/study" /> <property name ="username" value ="test" /> <property name ="password" value ="123456" /> </dataSource > </environment > </environments > <mappers > <mapper class ="com.test.mapper.TestMapper" /> </mappers > </configuration >
可选依赖 默认在导入依赖时,不会导入可选的依赖
1 <optional > true</optional >
排除依赖 使用exclusions标签排除依赖
1 2 3 4 5 6 7 8 9 10 11 12 <dependency > <groupId > org.junit.jupiter</groupId > <artifactId > junit-jupiter</artifactId > <version > 5.8.1</version > <scope > test</scope > <exclusions > <exclusion > <groupId > org.junit.jupiter</groupId > <artifactId > junit-jupiter-engine</artifactId > </exclusion > </exclusions > </dependency >
继承关系 一个Maven项目可以继承自另一个Maven项目。
创建子项目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <parent > <artifactId > MavenTest</artifactId > <groupId > org.example</groupId > <version > 1.0-SNAPSHOT</version > </parent > <modelVersion > 4.0.0</modelVersion > <artifactId > ChildModel</artifactId > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > </properties > </project >
parent节点,表示此Maven项目是父Maven项目的子项目,子项目直接继承父项目的groupId,子项目会直接继承父项目的所有依赖,除非依赖添加了optional标签。
可以由父Maven统一管理依赖,包括版本。子项目按需使用依赖,并无需指定版本号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <dependencyManagement > <dependencies > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.22</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.junit.jupiter</groupId > <artifactId > junit-jupiter</artifactId > <version > 5.8.1</version > <scope > test</scope > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.27</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.7</version > </dependency > </dependencies > </dependencyManagement >
1 2 3 4 5 6 7 <dependencies > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <scope > provided</scope > </dependency > </dependencies >
测试 通过使用test命令,可以一键测试所有位于test目录下的测试案例,请注意有以下要求:
测试类的名称必须是以Test结尾,比如MainTest
测试方法上必须标注@Test注解,实测@RepeatedTest无效
需要将配置插件升级到高版本,才能完美兼容Junit5,使@RepeatedTest、@BeforeAll生效。
1 2 3 4 5 6 7 8 9 10 <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-surefire-plugin</artifactId > <version > 2.22.0</version > </plugin > </plugins > </build >
打包项目 打包分为两种情况:
作为Jar依赖,使用package命令即可。
作为可执行程序
对于第二种情况,使用另一个插件进行打包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <plugin > <artifactId > maven-assembly-plugin</artifactId > <version > 3.1.0</version > <configuration > <descriptorRefs > <descriptorRef > jar-with-dependencies</descriptorRef > </descriptorRefs > <archive > <manifest > <addClasspath > true</addClasspath > <mainClass > com.test.Main</mainClass > </manifest > </archive > </configuration > <executions > <execution > <id > make-assembly</id > <phase > package</phase > <goals > <goal > single</goal > </goals > </execution > </executions > </plugin >
打包前会进行测试,可以选择执行Maven目标
来手动执行Maven命令,输入mvn package -Dmaven.test.skip=true 来以跳过测试的方式进行打包。