# Junit 单元测试工具

## 什么是单元测试?&#x20;

单元测试是 对软件中的最小测试单元进行检查和验证。或者换一个说法，就是对Java类里面的方法进行测试和验证.

Junit 4 就是Java中最出名的单元测试工具.

## 如何加载Junit?

有两种方法, 一种是用IDEA新建一个标准的Java工程，手动的将Junit 的jar包导入到工程中。具体步骤如下：

1. &#x20;新建一个标准Java工程
2. [下载所需的 jar 包](https://github.com/chesterzhang/intro_Java/tree/zhc_dev/resources), hamcrest-core-1.3.jar 和 junit-4.12.jar
3. 将两个 jar 包复制到 工程目录/lib 下
4. 选择IDEA左上角"File"-->"Project Structure"-->"Libraries"-->"+"-->"Java", 按下CTRL选择 工程目录/lib 下的两个 jar 包，点击"OK"

我们可以验证一下 Junit 是否被加载进了工程。 按CTRL + N, 勾选“include non-project-items",  搜索”Test“. 若出现"Test(org.junit)"说明Junit已经被加载进工程.

**然而这一种方法并不推荐，因为这样非常的繁琐.** 要是项目依赖的jar包很多怎么办？

还记得上一章的Maven吗? 没错， 用Maven 自动管理所需的依赖是最方便的。

### 用 Maven工程 加载Junit 工具

首先用 IDEA创建一个Maven 工程. 不使用模板。随后修改 pom.xml, 文件如下:&#x20;

```xml
<?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>indi.chester</groupId>
    <artifactId>JUnit</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>
```

我们额外地在dependencies标签下加入了 一个 dependency 标签，里面说明了 引入 Junit 和对应的版本号。非常简单, 不需要手动管理所需的 jar 包。

## 如何使用Junit?

用大白话来说, Junit 其实就是用来测试Java 类里面的方法的。我们举个简单例子, 创在 src/main/java 下创建一个Calculator 类

```java
public class Calculator {
    public int add(int a, int b){
        return a+b;
    }

    public float divide(int a, int b){
        if (b==0){
            throw new ArithmeticException("除数不能为0!");
        }
        return a*1f/b;
    }
}
```

随后在IDEA中右键代码编辑区-->"Generate..."-->"Test...", 进入自动生成测试类的窗口，"Testing library” 选择 Junit 4, "Test name" 维持默认也就是"CalculatorTest"， "Generate test methods for:" 将 add 和 divide 方法都勾选上， 点击"OK"。 IDEA 将会为我们在src/test/java路径下自动生成一个CalculatorTest类。

```java
import org.junit.Test;

public class CalculatorTest {
    

    @Test
    public void add() {
        
    }

    @Test
    public void divide() {
        
    }
}
```

Java中的测试类一般用 "被测试类Test" 的方式标明测试。测试类中的方法一般和被测试类中的方法同名，上方用 @Test 标识这是一个测试方法。随后我们可以在这个类中稍加修改，填写我们的测试方法。修改如下:

```java
import org.junit.Test;

public class CalculatorTest {
    private Calculator cal=new Calculator();

    @Test
    public void add() {
        int result=cal.add(1,2);
        System.out.println(result);
    }

    @Test
    public void divide() {
        float result=cal.divide(1,0);
        System.out.println(result);
    }
}
```

我们设置了一个私有成员 cal, 填充了 add 和 divide 方法。可以看出测试类的方法本质上就是在调用被测试的方法，我们需要填写的是测试用例的代码。比如 add 方法中计算 1+1， divide方法中计算 1 / 0.

### 运行起来&#x20;

运行测试类代码非常简单，和普通Java类的运行相同，支持run 和 debug 两种模式。 测试类的代码可以单独运行其中的某一个方法，IDEA中直接右键方法旁边的三角形，即可运行。也可以在IDEA中右键类名旁边的三角形运行所有测试方法。

我们运行整个测试类，测试Calculator所有方法。运行结果如下:

```
java.lang.ArithmeticException: 除数不能为0!

	at Calculator.divide(Calculator.java:9)
	at CalculatorTest.divide(CalculatorTest.java:14)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
```

控制台左侧可以看到 add 方法颜色为绿色，说明通过了 add(1,2)的测试用例, 而divide 方法为红色， 说明没有通过 1/0 的测试用例。观察控制台输出, 在Calculator的第14行中出现了报错。

这就是Junit的基本使用方法！
