JUnit 入门


#Java 笔记


JUnit 是一个测试框架,经常被拿来做单元测试。单元测试的粒度一般是方法。

我们看下如何编写单元测试。

如何编写单元测试

build.gradle 的默认内容如下:

plugins {
    id 'java'
}

group 'com.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

可以看到在 dependencies 中引入了junit依赖:

testCompile group: 'junit', name: 'junit', version: '4.12'

testCompile声明的依赖,只有在进行测试时才有效。又或者说,只有在src/test目录下的代码才会感知到 junit 依赖。

src/main/java中创建 Calculate 类,内容如下:

public class Calculate {

    public int add(int a, int b) {
        return a+b;
    }

}

src/test/java中创建 CalculateTest 类,内容如下:

import org.junit.Assert;
import org.junit.Test;

public class CalculateTest {

    @Test
    public void testAdd_01() {
        Calculate calculate = new Calculate();
        Assert.assertEquals(3, calculate.add(1, 2));
    }

    @Test
    public void testAdd_02() {
        Calculate calculate = new Calculate();
        Assert.assertEquals(4, calculate.add(1, 2));
    }

}

Assert 类中提供了一系列的断言方案,其中最常用的是assertEquals,第一个参数代表期望的值,第二个参数代表计算出的值。若两个值不相等,则抛出错误,认为测试失败。

在 testAdd_01 函数内部,鼠标右击,选择「Run testAdd_01」,会看到测试成功:

在 testAdd_02 函数内部,鼠标右击,选择「Run testAdd_02」,会看到测试失败:

在 testAdd_01 和 testAdd_02 函数外,鼠标右击,选择「Run CalculateTest」,会看到 testAdd_01 和 testAdd_02 都执行了:

几个问题:

Intellij IDEA 是如何支持 JUnit 测试的?

Intellij IDEA 默认集成了 JUnit 插件,所以可以通过右键菜单选项很方便的测试某个类中的单个测试、某个类的所有测试、某个包下的所有测试、以及 src/test 下的所有测试。

可以从 Intellij IDEA 自带的插件系统中找到该插件,如果禁用该插件,相应的右键菜单选项会消失。

如果要执行src/test目录下的所有测试代码,怎么做?

Intellij IDEA 中右击该目录,选择 Run All Tests

如果将 build.gradle 中的 testCompile 改成compile,那么能在src/main目录写测试代码吗?

能。

单测隔离

JUnit 的每一个@Test声明的测试中,会将非static变量或者非单例隔离开。

举个例子:

import org.junit.Test;

class TestBean {
    public int num = 1;
}

public class JUnitDemo {
    private TestBean testBean = new TestBean();

    @Test
    public void test01() {
        System.out.println("test01");
        System.out.println(testBean.num);  // 输出1
        // 将 num 修改为 10
        testBean.num = 10;
        System.out.println(testBean.num);  // 输出10
    }

    @Test
    public void test02() {
        System.out.println("test02");
        System.out.println(testBean.num);  // 还是输出1,可见没有受到 test01 的影响
        // 将 num 修改为 100
        testBean.num = 100;
        System.out.println(testBean.num);  // 输出 100
    }

}

运行 JUnitDemo中所有测试,输出如下:

test01
1
10
test02
1
100

test01先运行,会将 testBean.num 修改为 10。然后 test02 运行,但是开始时 testBean.num 的值仍是 1,可见没有受到 test01 的影响。

为什么会出现这种隔离的效果?因为运行 test01 和 test02 时,JUnitDemo 对象不是同一个。也就是 JUnit 为每一次测试生成一个新对象。这个很容易验证:

import org.junit.Test;

public class JUnitDemo {

    @Test
    public void test01() {
        System.out.println(this);
    }

    @Test
    public void test02() {
        System.out.println(this);
    }

}

运行所有测试,输出:

JUnitDemo@3d82c5f3
JUnitDemo@66cd51c3

输出结果不同,所以两次this也不是同一个。



( 本文完 )