Java单元测试Junit入门

作者: SpaceCat | 来源:发表于2019-04-06 16:07 被阅读1次

    JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。
    JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。
    From 百度百科

    1、从命令行运行Junit单元测试

    新建一个待测试的类,Compute.java:

    /**
     * Created by chengxia on 2019/3/28.
     */
    public class Compute {
        public static int add(int a, int b){
            return a+b;
        }
    }
    

    为上面的类新建一个测试类:

    import org.junit.Test;
    
    import static org.junit.Assert.assertEquals;
    
    /**
     * Created by chengxia on 2019/4/6.
     */
    public class ComputeTest {
        @Test
        public void testCompute(){
            int result = Compute.add(3,5);
            assertEquals(8,result);
        }
    }
    

    通过命令行进入上面两个源码文件所在的目录,然后编译并运行Junit测试。如下:

    $ ls
    Compute.java        ComputeTest.java
    $ javac -cp .:/Applications/IntelliJ\ IDEA.app/Contents/lib/junit-4.12.jar ComputeTest.java 
    $ ls
    Compute.class       Compute.java        ComputeTest.class   ComputeTest.java
    $ java -cp .:/Applications/IntelliJ\ IDEA.app/Contents/lib/junit-4.12.jar:/Applications/IntelliJ\ IDEA.app/Contents/lib/hamcrest-core-1.3.jar org.junit.runner.JUnitCore ComputeTest
    JUnit version 4.12
    .
    Time: 0.004
    
    OK (1 test)
    
    $ 
    

    上面需要注意:
    (1) 由于是引入的jar包路径中有空格,所以,在命令行中需要通过反斜杠进行转义。
    (2) 编译时,引入一个jar包(/Applications/IntelliJ\ IDEA.app/Contents/lib/junit-4.12.jar)就可以,在运行时必须同时引入/Applications/IntelliJ\ IDEA.app/Contents/lib/hamcrest-core-1.3.jar。否则,会报错。如下:

    $ java -cp .:/Applications/IntelliJ\ IDEA.app/Contents/lib/junit-4.12.jar org.junit.runner.JUnitCore ComputeTest
    JUnit version 4.12
    Exception in thread "main" java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at org.junit.runner.Computer.getSuite(Computer.java:28)
        at org.junit.runner.Request.classes(Request.java:75)
        at org.junit.runner.JUnitCommandLineParseResult.createRequest(JUnitCommandLineParseResult.java:118)
        at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
        at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
    Caused by: java.lang.ClassNotFoundException: org.hamcrest.SelfDescribing
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 17 more
    $ 
    

    很明显,junit-4.12.jar中用到了hamcrest-core-1.3.jar中的依赖。

    从上面运行junit测试的命令java -cp .:/Applications/IntelliJ\ IDEA.app/Contents/lib/junit-4.12.jar:/Applications/IntelliJ\ IDEA.app/Contents/lib/hamcrest-core-1.3.jar org.junit.runner.JUnitCore ComputeTest可以看出,这里直接运行的实际是JUnitCore类,测试类名只是作为一个参数传递给JUnitCore类的。这里,我们可以推测,JUnitCore类中肯定有main方法。实际上,借助IDEA的自动反编译打开这个类,其中确实有main方法定义。如下:

    package org.junit.runner;
    
    import junit.framework.Test;
    import junit.runner.Version;
    import org.junit.internal.JUnitSystem;
    import org.junit.internal.RealSystem;
    import org.junit.internal.TextListener;
    import org.junit.internal.runners.JUnit38ClassRunner;
    import org.junit.runner.notification.RunListener;
    import org.junit.runner.notification.RunNotifier;
    
    public class JUnitCore {
    
        ... ...
    
        public static void main(String... args) {
            Result result = (new JUnitCore()).runMain(new RealSystem(), args);
            System.exit(result.wasSuccessful()?0:1);
        }
    
        ... ...
    
    }
    

    2、在IDE中创建并运行单元测试(IntelliJ IDEA为例)

    上面的过程有助于我们理解单元测试的整个运行机制,实际开发中并没有这么麻烦。一般,我们都通过使用IDE来创建单元测试。这里我们,以IDEA为例说明(版本:IntelliJ IDEA 2017.1.5,自带有junit插件)。
    假设,工程中有如下Compute类:

    /**
     * Created by chengxia on 2019/3/28.
     */
    public class Compute {
        public static int add(int a, int b){
            return a+b;
        }
    }
    

    工程的结构如下:


    单元测试工程结构

    现在,我们要为这个类创建单元测试。首先,新建一个单元测试的文件夹。在IDEA中这需要两步:
    (1) 新建一个目录。


    New Directory for Unit Test

    (2) 将上面新建的目录设置为单元测试的根目录。


    Mark as Test Root

    完成之后,效果如下:


    新建测试目录完成

    接下来,创建单元测试的类。因为有插件,这里直接选中工作区中要创建单元测试的类,然后直接按快捷键command+shift+T,IDEA会自动弹出创建单元测试的指引。如下:

    Create new test guide

    点击Create New Test...,弹出如下对话框,选择junit的版本,选择要测试的方法,点OK即可。如下:

    Configure the Test Class

    注意,上图中提示junit4依赖的库找不到。点击Fix,然后,IDEA会提示,选择junit4 jar包路径,或者使用IDEA自带的junit4 jar包。我们这里选择IDEA自带的jar包。
    最后,IDEA自动生成的测试类(放在刚创建的test目录中)如下。


    Test Class Created by IDE

    我们要做的就是简单地将测试逻辑补全,如下:

    import org.junit.Test;
    
    import static org.junit.Assert.*;
    
    /**
     * Created by chengxia on 2019/4/6.
     */
    public class ComputeTest {
        @Test
        public void add() throws Exception {
            assertEquals(5,Compute.add(3,2));
        }
    
    }
    

    这样,我们在上面的测试类中,右键,然后选择Run 'ComputeTest',即可运行单元测试,效果如下。

    Running Result

    参考资料

    相关文章

      网友评论

        本文标题:Java单元测试Junit入门

        本文链接:https://www.haomeiwen.com/subject/ozbriqtx.html