Hamcrest使用教程

提到Java单元测试,一般想到JUnit,而Junit则很大程度上利用了Hamcrest,Hamcrest内部提供了很多Matcher可以帮我们容易的写测试规则。让我们无需在肉眼判断程序是否正常,各种Matcher帮你判断。

逻辑判断,对象规则,JavaBean规则,集合判断,数字判断,text判断,以及自定义规则。

在亲自使用一遍Hamcrest之后,就能理解Hamcrest的用法,及强大之处。易用但强大。

依赖

  • junit4
  • hamcrest2

使用

1 导入junit和hamcrest包。

        
            org.hamcrest
            hamcrest
            2.2
            test
        

        
            junit
            junit
            4.12
            test
        

2 编写常见的测试用例。我只是列出了常用的匹配器使用方式,主要的匹配器在Matchers类中可以直接看到。

如果引入的是CoreMatchers,能使用的Matcher会少一些

主要Mactcher列表:在下面的代码中对相应的匹配器有做解释

  • 核心:anything,describedAs,is
  • 逻辑:allOf,anyOf,not
  • 对象:equalTo,hasToString,instanceOf,isCompatibleType,notNullValue,nullValue,sameInstance
  • Beans:hasProperty
  • 集合:array,hasEntry,hasKey,hasValue,hasItem,hasItems,hasItemInArray
  • 数字:closeTo,greaterThan,greaterThanOrEqualTo,lessThan,lessThanOrEqualTo
  • 字符:equalToIgnoringCase,equalToIgnoringWhiteSpace,containsString,endsWith,startsWith
package me.aihe;

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class HelloAppTest {

    /**
     * 测试中最常用的equalTo。not内部增加了对equalTo的取反,本质上用的还是equalTo。
     * equalTo使用对象的equals方法来进行比较
     */
    @Test
    public void testTutorial(){
        TestObject first = new TestObject(0L,"123");
        TestObject second = new TestObject(1L,"123");
        TestObject third = new TestObject(0L,"123");
        assertThat(first, not(second));
        assertThat(first, equalTo(third));
        assertThat(second,not(third));

    }

    /**
     * Java中的任何对象都可以,不管任何的比较都会返回true
     */
    @Test
    public void testAnything(){
        assertThat("str",anything());
        assertThat(0,anything());
        assertThat(true,anything());
        assertThat(null,anything());
    }

    /**
     * 有时候我们觉得官方的测试失败消息不是那么的已读,那么自己重新指定错误提示消息。
     */
    @Test
    public void testdescribedAs(){
        String str = "str";
        String otherStr = "otherStr";
        assertThat(str,describedAs("当前的字符串是 %0",anything(),str));
        assertThat(str,describedAs("判断字符串 %0 是否等于 %1",is(otherStr),str,otherStr));
    }


    /**
     * allOf 当内部所有的Matcher都成立时才成立,相当于 &&
     * anyOf 当内部任何一个的Matcher成立时就成立,相当于 ||
     * not 对以上取反
     */
    @Test
    public void testLogical(){
        String str = "testStr testStr";
        assertThat(str,allOf( containsString("test"),containsString("Str"),containsString(" ")  ));
        assertThat(str,anyOf( containsString("test"),containsString("adas"),containsString(" ")  ));
        assertThat(str,allOf( containsString("test"),containsString("adas"),containsString(" ")  ));

    }

    /**
     * 测试Object的一些特性:
     *
     */
    @Test
    public void testObject(){
        TestObject testObject = new TestObject(10L,"12313");
        assertThat(testObject, instanceOf(TestObject.class) );
        assertThat(testObject, instanceOf(Object.class) );
        assertThat(testObject, sameInstance(Object.class) );
    }

    /**
     * 测试JavaBean是否有某个属性
     */
    @Test
    public void testBean(){
        TestObject testObject = new TestObject(10L,"12313");
        assertThat(testObject,hasProperty("id"));
    }


    /**
     * 测试集合
     */
    @Test
    public void testCollections(){
        HashMap map = new HashMap<>();
        map.put("orgId",123);
        map.put("operator",0);
        assertThat(map,hasKey("orgId"));
        assertThat(map,hasValue(123));

        List list = Arrays.asList("apple","banana","strawberry");
        assertThat(list,hasItem("apple"));
        assertThat(list.toArray(),hasItemInArray("apple"));
    }

    /**
     * 测试数字的比较
     */
    @Test
    public void testNumber(){
        int score = 90;
        int total = 100;
        assertThat(score,lessThan(total));
//        assertThat(score,greaterThan(total));
//        assertThat(score,greaterThanOrEqualTo(total));
//        assertThat(score,lessThanOrEqualTo(total));
    }

    @Test
    public void testText(){
        String text = "Hamcrest comes bundled with lots of useful matchers, but you’ll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you’ll eliminate code duplication and make your tests more readable!";
        assertThat(text,containsString("comes"));
        assertThat(text,startsWith("Hamcrest"));
        assertThat(text,endsWith("readable!"));
        assertThat(text,equalTo("readable!"));

    }

    /**
     * 测试自定义的匹配器
     */
    @Test
    public void testCustomMatcher(){
        String o = "";
        assertThat(o,new isSuccess());
        assertThat(null,new isSuccess());
    }


    /**
     * 只要对象不为空就为成功
     */
    public static class isSuccess extends TypeSafeMatcher{

        @Override
        protected boolean matchesSafely(Object o) {
            return o != null;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("is success");
        }
    }


    public static class TestObject{
        Long id;
        String msg;

        public TestObject(Long id, String msg) {
            this.id = id;
            this.msg = msg;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            TestObject that = (TestObject) o;
            return id.equals(that.id) &&
                    msg.equals(that.msg);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, msg);
        }
    }
}

自定义Macther

1 继承Matcher类,然后写matcher逻辑,加上macther的描述信息。

  /**
     * 只要对象不为空就为成功
     */
    public static class isSuccess extends TypeSafeMatcher{

        @Override
        protected boolean matchesSafely(Object o) {
            return o != null;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("is success");
        }
    }

2 使用自定义Matcher

  @Test
    public void testCustomMatcher() {
        String o = "";
        assertThat(o, new isSuccess());
        assertThat(null, new isSuccess());
    }

最后

Hamcrest用起来还是很方便的,在写好单元测试的道路上又多了一个利器,不需要肉眼去判断我们的程序是否执行正常,用Hamcrest就可以帮我们检查。

参考:http://hamcrest.org/JavaHamcrest/index

你可能感兴趣的:(Hamcrest使用教程)