Junit测试集锦

前言:

一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地失去了原有的结构,最终变成了一团乱麻。所以在开发过程中,对于程序员来说,测试是非常重要的。言归正传,开始Junit的测试。

eclipse/Myeclipse中用Junit进行单元测试很方便,尤其是Junit4引入了很多Annotation注解以后。

一、核心——断言

断言是编写测试用例的核心实现方式,即期望值是多少,测试的结果是多少,以此来判断测试是否通过。

1. 断言核心方法

assertArrayEquals(expecteds, actuals) 查看两个数组是否相等。
assertEquals(expected, actual) 查看两个对象是否相等。类似于字符串比较使用的equals()方法
assertNotEquals(first, second) 查看两个对象是否不相等。
assertNull(object) 查看对象是否为空。
assertNotNull(object) 查看对象是否不为空。
assertSame(expected, actual) 查看两个对象的引用是否相等。类似于使用“==”比较两个对象
assertNotSame(unexpected, actual) 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象
assertTrue(condition) 查看运行结果是否为true。
assertFalse(condition) 查看运行结果是否为false。
assertThat(actual, matcher) 查看实际值是否满足指定的条件
fail() 让测试失败

2. 示例

package test;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

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. 说明

@Before 初始化方法
@After 释放资源
@Test 测试方法,在这里可以测试期望异常和超时时间
@Ignore 忽略的测试方法
@BeforeClass 针对所有测试,只执行一次,且必须为static void
@AfterClass 针对所有测试,只执行一次,且必须为static void
@RunWith 指定测试类使用某个运行器
@Parameters 指定测试类的测试数据集合
@Rule 允许灵活添加或重新定义测试类中的每个测试方法的行为
@FixMethodOrder 指定测试方法的执行顺序

2. 执行顺序

一个测试类单元测试的执行顺序为:

@BeforeClass –> @Before –> @Test –> @After –> @AfterClass

每一个测试方法的调用顺序为:

@Before –> @Test –> @After

3. 示例

package test;

import static org.junit.Assert.*;

import org.junit.*;

public class JDemoTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		System.out.println("================in BeforeClass================");
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		System.out.println("================in AfterClass=================");
	}

	@Before
	public void before() {
		System.out.println("in Before");
	}

	@After
	public void after() {
		System.out.println("in After");
	}

	@Test(timeout = 10000)
	public void testadd() {
		JDemo a = new JDemo();
		assertEquals(6, a.add(3, 3));
		System.out.println("in Test ----Add");
	}

	@Test
	public void testdivision() {
		JDemo a = new JDemo();
		assertEquals(3, a.division(6, 2));
		System.out.println("in Test ----Division");
	}

	@Ignore
	@Test
	public void test_ignore() {
		JDemo a = new JDemo();
		assertEquals(6, a.add(1, 5));
		System.out.println("in test_ignore");
	}

	@Test
	public void teest_fail() {
		fail();
	}
}

class JDemo extends Thread {

	int result;

	public int add(int a, int b) {
		try {
			sleep(1000);
			result = a + b;
		} catch (InterruptedException e) {
		}
		return result;
	}

	public int division(int a, int b) {
		return result = a / b;
	}
}

执行结果:

=================in BeforeClass================
in Before
in Test ----Add
in After
in Before
in Test ----Division
in After
===================in AfterClass=================

图中左上红框中部分表示Junit运行结果,5个成功(1个忽略),1个错误,1个失败。(注意错误和失败不是一回事,错误说明代码有错误,而失败表示该测试方法测试失败)

左下红框中则表示出了各个测试方法的运行状态,可以看到成功、错误、失败、失败各自的图标是不一样的,还可以看到运行时间。

右边部分则是异常堆栈,可查看异常信息。

三、实例总结

1. 参数化测试

有时一个测试方法,不同的参数值会产生不同的结果,那么我们为了测试全面,会把多个参数值都写出来并一一断言测试,这样有时难免费时费力,这是我们便可以采用参数化测试来解决这个问题。参数化测试就好比把一个“输入值,期望值”的集合传入给测试方法,达到一次性测试的目的。

package test;

import static org.junit.Assert.*;

import java.util.Arrays;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class FibonacciTest {

    @Parameters(name = "{index}: fib({0})={1}")
    public static Iterable<Object[]> data() {
        return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
                { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
    }

    private int input;
    private int expected;

    public FibonacciTest(int input, int expected) {
        this.input = input;
        this.expected = expected;
    }

    @Test
    public void test() {
        assertEquals(expected, Fibonacci.compute(input));
    }
}

class Fibonacci {

	public static int compute(int input) {
		int result;
		switch (input) {
		case 0:
			result = 0;
			break;
		case 1:
		case 2:
			result = 1;
			break;
		case 3:
			result = 2;
			break;
		case 4:
			result = 3;
			break;
		case 5:
			result = 5;
			break;
		case 6:
			result = 8;
			break;
		default:
			result = 0;
		}
		return result;
	}
}

@Parameters注解参数name,实际是测试方法名称。由于一个test()方法就完成了所有测试,那假如某一组测试数据有问题,那在Junit的结果页面里该如何呈现?因此采用name实际上就是区分每个测试数据的测试方法名。

2. 打包测试

同样,如果一个项目中有很多个测试用例,如果一个个测试也很麻烦,因此打包测试就是一次性测试完成包中含有的所有测试用例。

package test;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({ AssertTests.class, FibonacciTest.class, JDemoTest.class })
public class AllCaseTest {

}

这个功能也需要使用一个特殊的Runner ,需要向@RunWith注解传递一个参数Suite.class 。同时,我们还需要另外一个注解@Suite.SuiteClasses,来表明这个类是一个打包测试类。并将需要打包的类作为参数传递给该注解就可以了。至于AllCaseTest随便起一个类名,内容为空既可。运行AllCaseTest类即可完成打包测试

3. 异常测试

异常测试与普通断言测试不同,共有三种方法,其中最为灵活的是第三种,可以与断言结合使用

第一种:

  @Test(expected= IndexOutOfBoundsException.class)
  public void empty() {
       new ArrayList<Object>().get(0);
  }

第二种:

  @Test
  public void testExceptionMessage() {
      try {
          new ArrayList<Object>().get(0);
          fail("Expected an IndexOutOfBoundsException to be thrown");
      } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) {
          assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0"));
      }
  }

第三种:

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
        List<Object> list = new ArrayList<Object>();

        thrown.expect(IndexOutOfBoundsException.class);
        thrown.expectMessage("Index: 0, Size: 0");
        list.get(0);
        Assert.assertEquals(1, list.get(0));
    }

在上述几种方法中,无论是expected还是expect都表示期望抛出的异常,假如某一方法,当参数为某一值时会抛出异常,那么使用第一种方法就必须为该参数单独写一个测试方法来测试异常,而无法与其他参数值一同写在一个测试方法里,所以显得累赘。第二种方法虽然解决这个问题,但是写法不仅繁琐也不利于理解。而第三种犯法,不仅能动态更改期望抛出的异常,与断言语句结合的也非常好,因此推荐使用该方法来测试异常。

4. 限时测试

有时为了防止出现死循环或者方法执行过长(或检查方法效率),而需要使用到限时测试。顾名思义,就是超出设定时间即视为测试失败。共有两种写法。

第一种:

@Test(timeout=1000)
public void testWithTimeout() {
  ...
}

第二种:

public class HasGlobalTimeout {
    public static String log;

    @Rule
    public Timeout globalTimeout = new Timeout(10000); // 10 seconds max per method tested

    @Test
    public void testInfiniteLoop1() {
        log += "ran1";
        for (;;) {
        }
    }

    @Test
    public void testInfiniteLoop2() {
        log += "ran2";
        for (;;) {
        }
    }
}

后记:

正是由于JUnit的开放性和简单易行,才会引出这篇介绍文章。但技术总在不断地更新,而且我们对测试并没有非常深入的理解;我们可以将一个复杂的概念简化成一句非常容易理解的话。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 20:16:47

Junit测试集锦的相关文章

android junit 测试 简要步骤

android junit 测试 1.新建一个类继承TestCase这个类 2.AndroidManifest.xml, 加入<uses-library android:name="android.test.runner" /> <!-- 记住这个一要放在application外面,不然会出现配置错误 信息 -->      <instrumentation android:name="android.test.InstrumentationTe

Junit测试Controller(MockMVC使用),传输@RequestBody数据解决办法

一.单元测试的目的 简单来说就是在我们增加或者改动一些代码以后对所有逻辑的一个检测,尤其是在我们后期修改后(不论是增加新功能,修改bug),都可以做到重新测试的工作.以减少我们在发布的时候出现更过甚至是出现之前解决了的问题再次重现. 这里主要是使用MockMvc对我们的系统的Controller进行单元测试. 对数据库的操作使用事务实现回滚,及对数据库的增删改方法结束后将会还远数据库. 二.MockMvc的使用 1.首先我们上一个例子, import org.apache.commons.log

Junit测试中的setup和teardown 和 @before 和 @After 方法

这几天做Junit测试接触到了setup和teardown两个方法,简单的可以这样理解它们,setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作. 需要注意的是Junit3中每个测试方法执行时都会执行它们,而不是一个类中执行一次,查了查资料,JUnit4版本采用注解的方式可以实现一个类只执行一次,下面看看测试代码: jar下载地址: http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22junit%22%20

复利计算器(软件工程)及Junit测试———郭志豪

计算:1.本金为100万,利率或者投资回报率为3%,投资年限为30年,那么,30年后所获得的利息收入:按复利计算公式来计算就是:1,000,000×(1+3%)^30 客户提出: 2.如果按照单利计算,本息又是多少呢? 3.假如30年之后要筹措到300万元的养老金,平均的年回报率是3%,那么,现在必须投入的本金是多少呢? 4.利率这么低,复利计算收益都这么厉害了,如果拿100万元去买年报酬率10%的股票,若一切顺利,过多长时间,100万元就变成200万元呢? 5.如果我希望在十年内将100万元变

正则表达式 和 junit测试

需要知道一些常规的正则表达式语句,然后可以仿照规则写出一下正则表达式语句.然后是关于junit测试. 知道了一个之前看过的文档,然后有功夫就看一下那个文档就可以,或者后面找时间搜索一下. 正则表达式是一个字符串: 由^开头 由$结尾. []表示可取值的范围. \\d表示数字. 下面两个表达式等效: ^[0-9]*$ ^\\d*$ 都表示若干数字 下面这个表示多个汉字: ^[\u4e00-\u9fa5]{0,}$ 汉字的码集是从\u4e00-\u9fa5 所有英文字母和数字: ^[a-zA-Z0-

【Java 语言生态篇】Junit 测试单元

01 概述 JUnit是一个由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework).Junit测试是白盒测试.JUnit有它自己的JUnit扩展生态圈.多数Java的开发环境都已经集成了JUnit作为单元测试的工具.[1] JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试.他是用于单元测试框架体系xUnit的一个实例(用于java语言).它包括以下特性: 1.用于测试期望结果的断言(Asser

Android Day02-Android中单元测试(junit测试)&monkey测试

Android中junit测试有2种实现方式 第1种:一般Android工程的实现方式 1.在清单文件中添加2项内容 首先在AndroidManifest.xml中加入下面红色代码: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.itcast.action" android:versionCode="1"  android:v

Junit 测试断言说明

Assert.assertEquals("发生错误时报告消息","预期值","生产值"); Assert.assertEquals("精确两位小数点",3.33,10.0/3.0,0.01); Assert.assertNotNull("");//验证是否为非空 Assert.assertNull(""); //验证是否为空 Assert.assertSame("",

无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.demo1" /> 上面targetPackage指定的包要和应用的package相同. (2)在清单文件中ap