Java开发测试工具用法简略记录——Junit4 And EasyMock

时间:2021-04-17 11:35:23

Junit4

Junit是Java中用于测试的一个单元库,其包含以下几项重要功能:

@Test注解驱动测试

public class RegularExpressionJUnit4Test {
private static String zipRegEx = "^\\d{5}([\\-]\\d{4})?$";
private static Pattern pattern;
@Test
public void verifyZipCodeNoMatch() throws Exception{
Matcher mtcher = this.pattern.matcher("2211");
boolean notValid = mtcher.matches();
assertFalse("Pattern did validate zip code", notValid);
}
}

Junit4的异常测试

设置@Test的 expected 、timeout等参数来测试异常和超时。

    @Test(expected=IndexOutOfBoundsException.class)
public void verifyZipCodeGroupException() throws Exception{
Matcher mtcher = this.pattern.matcher("22101-5051");
boolean isValid = mtcher.matches();
mtcher.group(2);
}

@Test(timeout=1)
public void verifyFastZipCodeMatch() throws Exception{
Pattern pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");
Matcher mtcher = pattern.matcher("22011");
boolean isValid = mtcher.matches();
assertTrue("Pattern did not validate zip code", isValid);
}

Junit4忽略测试

忽略坏掉或不完整的测试,可以通过添加@Ignore注解来实现。

    @Ignore("this regular expression isn't working yet")
@Test
public void verifyZipCodeMatch() throws Exception{
Pattern pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})");
Matcher mtcher = pattern.matcher("22011");
boolean isValid = mtcher.matches();
assertTrue("Pattern did not validate zip code", isValid);
}

Junit4测试固件

固件是测试前和测试后必须执行的操作,通过注解@BeforeClass、@AfterClass、@Before、@After来实现。在类层次,有 @BeforeClass 和 @AfterClass,在方法(或测试)层次,有 @Before 和 @After。

    @Before
public static void setUpBeforeClass() throws Exception {
pattern = Pattern.compile(zipRegEx);
}

@Test
public void verifyZipCodeNoMatch() throws Exception{
Matcher mtcher = this.pattern.matcher("2211");
boolean notValid = mtcher.matches();
assertFalse("Pattern did validate zip code", notValid);
}

Junit4套件测试

捆绑多个测试类,进行以组为单位的测试。使用@Runwith和@SuiteClasses注解来实现:

    @RunWith(Suite.class)
@SuiteClasses({ParametricRegularExpressionTest.class,
RegularExpressionTest.class,
TimedRegularExpressionTest.class})
public class JUnit4Suite {}

Junit4参数测试

偶尔,应用程序的业务逻辑要求您编写许多不定量的测试来保证其健壮。在 JUnit 之前的版本中,这种场景很不方便,主要是因为一个测试中方法的参数组各不相同,意味着要为每一个单独的组编写一个测试用例。
详情参照博客:https://www.ibm.com/developerworks/cn/education/java/j-junit4/index.html

EasyMock

EasyMock 是一个针对 Java 编程语言的开放源码 mock 对象库,可以帮助您快速轻松地创建用于这些用途的 mock 对象。EasyMock 使用动态代理,让您只用一行代码就能够创建任何接口的基本实现。
mock 对象有助于从测试中消除依赖项。它们使测试更单元化。涉及 mock 对象的测试中的失败很可能是要测试的方法中的失败,不太可能是依赖项中的问题。这有助于隔离问题和简化调试。
添加依赖:

    <dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.0</version>
</dependency>

创建mock对象——EasyMock.createMock(myInterface.class)

假设我们有一个这样一个接口:

    import java.io.IOException;

public interface ExchangeRate {
double getRate(String inputCurrency, String outputCurrency) throws IOException;
}

现在我们另一个类的测试依赖于这个接口,它需要一个该接口的实现才能继续测试。这时,我们不需要真的创建一个该接口的实现类,并且实例化它。我们只需要用Mock创建一个ExchangeRate接口的模拟实现即可,简单快捷:

        ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);//步骤1
EasyMock.expect(mock.getRate("USD", "EUR")).andReturn(1.5);//步骤2
EasyMock.replay(mock);//步骤3

没错,就是这么简单,只需要3步我们就创建成功了。
1. 步骤1,使用EasyMock的静态方法createMock()创建接口的Mock对象。
2. 步骤2,使用EasyMock的静态方法expect()设置期望值。把方法作为参数传递给 EasyMock.expect() 方法。然后调用 andReturn() 指定调用这个方法应该得到什么结果。
3. 步骤3,调用 EasyMock.replay() 方法,让 mock 准备在下一次调用时重放记录的数据。

测试异常

mock 最常见的用途之一是测试异常条件。例如,无法简便地根据需要制造网络故障,但是可以创建模拟网络故障的 mock。

    EasyMock.expect(mock.getRate("USD", "EUR")).andThrow(new IOException());

这里的新东西是 andThrow() 方法。顾名思义,它只是让 getRate() 方法在被调用时抛出指定的异常。

放宽测试参数

在默认情况下,EasyMock 只允许测试用例用指定的参数调用指定的方法。但是,有时候这有点儿太严格了,所以有办法放宽这一限制。例如,假设希望允许把任何字符串传递给 getRate() 方法,而不仅限于 USD 和 EUR。那么,可以指定 EasyMock.anyObject() 而不是显式的字符串,如下所示:

       (String) EasyMock.anyObject(),
(String) EasyMock.anyObject())).andReturn(1.5);

类似的方法还有:

    //非空参数
EasyMock.expect(mock.getRate(
(String) EasyMock.notNull(),
(String) EasyMock.notNull())).andReturn(1.5);
//正则表达式参数
EasyMock.expect(mock.getRate(
(String) EasyMock.matches("[A-Z][A-Z][A-Z]"),
(String) EasyMock.matches("[A-Z][A-Z][A-Z]"))).andReturn(1.5);

EasyMock.anyInt()
EasyMock.anyShort()
EasyMock.anyByte()
EasyMock.anyLong()
EasyMock.anyFloat()
EasyMock.anyDouble()
EasyMock.anyBoolean()
//还可以使用 EasyMock.lt(x) 接受小于 x 的任何值,或使用 EasyMock.gt(x) 接受大于 x 的任何值。

严格的mock次序检查

EasyMock 不仅能够检查是否用正确的参数调用预期的方法。它还可以检查是否以正确的次序调用这些方法,而且只调用了这些方法。在默认情况下,不执行这种检查。要想启用它,应该在测试方法末尾调用 EasyMock.verify(mock)。
检查是否只调用 getRate() 一次:

    public void testToEuros() throws IOException {
Currency expected = new Currency(3.75, "EUR");
ExchangeRate mock = EasyMock.createMock(ExchangeRate.class);
EasyMock.expect(mock.getRate("USD", "EUR")).andReturn(1.5);
EasyMock.replay(mock);
Currency actual = testObject.toEuros(mock);
assertEquals(expected, actual);
EasyMock.verify(mock);
}

该功能基本上只有在大型项目中才会用到,不易理解,等需要用到时再回来查,查阅地址:https://www.ibm.com/developerworks/cn/java/j-easymock.html#artrelatedtopics