在Java开发领域,单元测试框架众多,JUnit和TestNG是其中最流行的两个。随着测试用例的规模和复杂度的增长,单元测试代码往往会变得难以阅读和表达。这时,Hamcrest框架就能大显身手,帮助编写出表达性强的单元测试。
Hamcrest框架通过改进方法名的选用,提高了测试用例的可读性。以下是一些示例:
Java代码:
assertThat(actualValue, is(equalTo(expectedValue)));
assertThat(employee, hasProperty("firstName"));
assertThat(employee.getMaritalStatus(), isIn(new String[]{"Married", "Single - Never Married", "Widow", "Divorced"}));
Hamcrest方法不允许将苹果和橘子进行比较,而是强制进行类型安全的比较。这在编写测试用例时非常有用,因为不会比较不匹配的类型。Hamcrest大量使用Java泛型来确保类型安全。以下是一些示例:
assertThat(employee.isManager(), is("true"));
Hamcrest允许在单个assertThat语句中编写多个条件。可以使用逻辑条件如or/and来组合多个条件。可以编写测试用例,其中条件必须全部匹配,或者只需匹配任一条件。以下是一些示例:
assertThat(employee.getFirstName(), allOf(notNullValue(), is("John")));
Hamcrest支持丰富的匹配器集合,以下是一些示例:
Hamcrest不仅提供了丰富的功能集,还完全支持创建自定义匹配器。要编写自定义匹配器,需要从TypeSafeMatcher基类扩展。以下是从Hamcrest文档中取出的一个简单示例:
public class IsNotANumber extends TypeSafeMatcher {
@Override
public boolean matchesSafely(Double number) {
return number.isNaN();
}
public void describeTo(Description description) {
description.appendText("This is not a number");
}
@Factory
public static <T> Matcher<Double> notANumber() {
return new IsNotANumber();
}
}
编写测试用例时使用Hamcrest构造可以提高测试用例的可读性,使其易于理解和维护。
要使用Hamcrest的所有功能,需要在pom.xml中添加以下Maven依赖:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
import com.test.matchers.Employee;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
public class EmployeeTest {
private Employee employee;
@Before
public void initEmployee() {
employee = new Employee();
employee.setFirstName("John");
employee.setDesignation("Manager");
employee.setAge(30);
}
@Test
public void firstNameCannotBeNull() {
assertThat("", employee.getFirstName(), notNullValue());
}
@Test
public void firstNameEqualsJohn() {
assertThat("", employee.getFirstName(), is("John"));
}
@Test
public void designationShouldBeManagerOrContractor() {
assertThat(employee.getDesignation(), anyOf(is("Manager"), is("Contractor")));
}
@Test
public void employeeShouldBeOlderThan20() {
assertThat(employee.getAge(), greaterThan(20L));
}
@Test
public void employeeHasAgeProperty() {
assertThat(employee, hasProperty("age"));
}
}