上一篇: jekyll 教程入门

一、简介

JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中为最成功的一个。来自JUnit的体验对测试驱动开发是很重要的,所以一些 JUnit知识经常 和测试驱动开发的讨论融合在一起。可以参考Kent Beck的 《Test-Driven Development: By Example》一书(有中文版和影印版)。

本文,对JUnit4的下载安装、基本测试方法及运行,配合实例进行基础介绍。帮助读者看完之后,就可以将JUnit4运用到单元测试中去。而JUnit4的更多功能可以参考后续的JUnit4使用进阶二

二、下载安装

JUnit当前版本是4.11,如果,你的工程是使用Maven进行管理构建,那么只需要在工程的pom.xml文件中添加如下依赖信息:

<dependency>
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>4.11</version>
  		<scope>test</scope>
</dependency>

否则,在你的测试classpath中放置下面两个jar:junit.jarhamcrest-core.jar,这两个jar可以在这里找到并下载。

三、一个简单的模版

package com.example.foo;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link Foo}.
 *
 * @author user@example.com (John Doe)
 */
@RunWith(JUnit4.class)
public class FooTest {

	@Test
	public void thisAlwaysPasses() {
	}

	@Test
	@Ignore
	public void thisIsIgnored() {
	}
}

这个模版是不是很简单!

  • 需要测试的方法,只需要通过@Test标注出来就可以了。

  • 测试类只需要添加@RunWith注释,不再需要继承junit.framework.TestCase这个父类了。

当然了,JUnit4还提供了很多特色功能,后面我们会一一介绍。

四、运行测试

  • 在命令行,对写好的测试类,进行测试很简单,只需要下面一个命令就ok了:

      java -cp .:/usr/share/java/junit.jar org.junit.runner.JUnitCore [test class name]
    
  • 在IDE里面进行测试就更简单了,Netbeans, EclipseIntelliJ Idea都内置了图形化的测试运行器。

测试类如何运行,是由@RunWith注释来决定。JUnit4当前版本的默认基本测试方式是JUnit4.class。除此之外,还有一些其他特殊的,我们将在JUnit4 使用进阶四中进行介绍。

五、JUnit4的核心之一是断言

JUnit4框架主要是通过断言来判断运行结果正确与否,针对Java的原生类型(long,boolean,float…)或者Objects或者数组,JUnit都提供了对应的断言方法。

下面,我们先来看个例子:

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.both;
import static org.junit.matchers.JUnitMatchers.containsString;
import static org.junit.matchers.JUnitMatchers.everyItem;
import static org.junit.matchers.JUnitMatchers.hasItems;

import java.util.Arrays;

import org.hamcrest.core.CombinableMatcher;
import org.junit.Test;

public class AssertTests {
  @Test
  public void testAssertArrayEquals() {
    byte[] expected = "trial".getBytes();
    byte[] actual = "trial".getBytes();
    org.junit.Assert.assertArrayEquals("failure - byte arrays not same", expected, actual);
  }

  @Test
  public void testAssertEquals() {
    org.junit.Assert.assertEquals("failure - strings not same", 5l, 5l);
  }

  @Test
  public void testAssertFalse() {
    org.junit.Assert.assertFalse("failure - should be false", false);
  }

  @Test
  public void testAssertNotNull() {
    org.junit.Assert.assertNotNull("should not be null", new Object());
  }

  @Test
  public void testAssertNotSame() {
    org.junit.Assert.assertNotSame("should not be same Object", new Object(), new Object());
  }

  @Test
  public void testAssertNull() {
    org.junit.Assert.assertNull("should be null", null);
  }

  @Test
  public void testAssertSame() {
    Integer aNumber = Integer.valueOf(768);
    org.junit.Assert.assertSame("should be same", aNumber, aNumber);
  }

  // JUnit Matchers assertThat
  @Test
  public void testAssertThatBothContainsString() {
    org.junit.Assert.assertThat("albumen", both(containsString("a")).and(containsString("b")));
  }

  @Test
  public void testAssertThathasItemsContainsString() {
    org.junit.Assert.assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
  }

  @Test
  public void testAssertThatEveryItemContainsString() {
    org.junit.Assert.assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
  }

  // Core Hamcrest Matchers with assertThat
  @Test
  public void testAssertThatHamcrestCoreMatchers() {
    assertThat("good", allOf(equalTo("good"), startsWith("good")));
    assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
    assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
    assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
    assertThat(new Object(), not(sameInstance(new Object())));
  }
}

注意:

  1. assertEqualsassertSame 的区别在于,前者是调用期待值equals方法来判断真实值(expected.equals(actual)),而后者是判断期待值真实值是否是同一个对象(expected == actual)。
  2. 例子中,这样调用org.junit.Assert.assertEquals("failure - strings not same", 5l, 5l);是不是觉得有点累,没关系,我们可以通过JDK1.5中的静态导入(import static)来简化这一切,看下面的代码。

简化后的例子:

package tangzhi.mytest;

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.both;
import static org.junit.matchers.JUnitMatchers.containsString;
import static org.junit.matchers.JUnitMatchers.everyItem;
import static org.junit.matchers.JUnitMatchers.hasItems;

import static org.junit.Assert.*;
    
import java.util.Arrays;

import org.hamcrest.core.CombinableMatcher;
import org.junit.Test;

public class AppTest {
  @Test
  public void testAssertArrayEquals() {
    byte[] expected = "trial".getBytes();
    byte[] actual = "trial".getBytes();
    assertArrayEquals("failure - byte arrays not same", expected, actual);
  }

  @Test
  public void testAssertEquals() {
    assertEquals("failure - strings not same", 5l, 5l);
  }

  @Test
  public void testAssertFalse() {
    assertFalse("failure - should be false", false);
  }

  @Test
  public void testAssertNotNull() {
    assertNotNull("should not be null", new Object());
  }

  @Test
  public void testAssertNotSame() {
    assertNotSame("should not be same Object", new Object(), new Object());
  }

  @Test
  public void testAssertNull() {
    assertNull("should be null", null);
  }

  @Test
  public void testAssertSame() {
    Integer aNumber = Integer.valueOf(768);
    assertSame("should be same", aNumber, aNumber);
  }

  // JUnit Matchers assertThat
  @Test
  public void testAssertThatBothContainsString() {
    assertThat("albumen", both(containsString("a")).and(containsString("b")));
  }

  @Test
  public void testAssertThathasItemsContainsString() {
    assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
  }

  @Test
  public void testAssertThatEveryItemContainsString() {
    assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
  }

  // Core Hamcrest Matchers with assertThat
  @Test
  public void testAssertThatHamcrestCoreMatchers() {
    assertThat("good", allOf(equalTo("good"), startsWith("good")));
    assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
    assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
    assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
    assertThat(new Object(), not(sameInstance(new Object())));
  }
}

在上面的代码中,我们静态导入了import static org.junit.Assert.*;后,在测试类中就可以直接使用assertEquals这些方法了。是不是很方便!

常用的断言方法有:

assertTrue([message ,] condition);
assertFalse([message ,] condition);
assertEquals([message ,] expected, actual);
assertNotEquals([message ,] first, second);
assertArrayEquals([message ,] expecteds, actuals);
assertNotNull([message ,] object);
assertNull([message ,] object);
assertSame([message ,] expected, actual);
assertNotSame([message ,] unexpected, actual);
assertThat([message ,] actual, matcher);

从上面的列表可以看出:

  1. 大部分断言方法的参数顺序都是:[Message] 期待值 真实值,第一个参数是个可选字符串,出错时的描述信息。第二个参数是期待值,第三个参数是真实值。

  2. 只有一个断言方法assertThat的参数顺序例外:可选的出错提示信息、真实值和一个Matcher对象。它参数中的期待值与真实值的顺序,与其他断言方法的参数顺序正好相反。

这个assertThat方法是断言中的神器,后面我们会在进阶三介绍!敬请期待吧!

六、小结

前面我们介绍了JUnit4的基本知识。至此,你已经可以使用JUnit4进行代码测试了。如果你想知道更多信息,可以继续看看JUnit 使用进阶二