Mockito 学习笔记

Mockito 学习

描述

Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 JDBC 中的ResultSet 对象),用一个虚拟的对象(Mock 对象)来创建以便测试的测试方法。

Mock 最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

下面是进行总结的一些使用情况的场景:


依赖包

	<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.10.19</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-all -->
		<dependency>
			<groupId>org.hamcrest</groupId>
			<artifactId>hamcrest-all</artifactId>
			<version>1.3</version>
			<scope>test</scope>
		</dependency>

自动装配三种方式

  1. 通过对进行注解
@RunWith(MockitoJUnitRunner.class)
public class MockByRunnerTest {}
  1. 通过在方法中进行调用初始化
public class MockByAnnotationTest {

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
    }
}
  1. 通过使用Rule进行注解
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();

常见的命令

深度Mock ,可以让其它对象继承Mock属性
public class DeepMockTest {

      public class Lession03Service {

        public Lession03 get(){
            throw  new RuntimeException();
        }
    	}
    public class Lession03 {
      public void foo(){
          throw  new RuntimeException();
      }
  	}
    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Lession03Service lession03Service;

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testDeepMock(){
        Lession03 lession03 = lession03Service.get();
        lession03.foo();
    }
}

常用的Stubbing 操作
@RunWith(MockitoJUnitRunner.class)
public class StubbingTest {

    public class StubbingService {

        public int getI(){
            System.out.println("===== get I ======");
            return 10;
        }

        public String getS(){
            System.out.println("========= get S  ==========");
            throw new RuntimeException();
        }
    }

    private List<String> list;

    @Before
    public void init(){
        this.list = mock(ArrayList.class);
    }
    
    @Test
    public  void hosToUseStubbing(){
        when(list.get(0)).thenReturn("first");
        assert list.get(0).equals("first");

        when(list.get((anyInt()))).thenThrow(new RuntimeException());
        try{
            list.get(0);
            fail();
        }catch (Exception e){
            assert e.getClass().equals(RuntimeException.class);
        }
    }

    @Test
    public void howToStubbingVoidMethod(){
        doNothing().when(list).clear();
        list.clear();
        verify(list, times(1)).clear();

        doThrow(RuntimeException.class).when(list).clear();

        try{
            list.clear();
            fail();
        }catch (Exception e){
            assert e.getClass().equals(RuntimeException.class);
        }
    }

    @Test
    public void stubbingDoReturn(){

        when(list.get(0)).thenReturn("first");
        doReturn("second").when(list).get(1);
        assert list.get(0).equals("first");
        assert list.get(1).equals("second");

    }

    @Test
    public void iterateSubbing() {
        when(list.size()).thenReturn(1,2,3,4);

        assert list.size() == 1;
        assert list.size() == 2;
        assert list.size() == 3;
        assert list.size() == 4;
        assert list.size() == 4;
    }

    @Test
    public void stubbingWithAnswer(){
        when(list.get(anyInt())).thenAnswer(invocationOnMock -> {
            Integer index = invocationOnMock.getArgument(0, Integer.class);
            return String.valueOf(index *  10);
        });
        assert list.get(0).equals("0");
        assert list.get(999).equals("9990");

    }

    @Test
    public void stubbingWithRealCall(){
        StubbingService stubbingService = mock(StubbingService.class);

        when(stubbingService.getS()).thenReturn("Alex");
        assert stubbingService.getS().equals("Alex");

        when(stubbingService.getI()).thenCallRealMethod();
        assert stubbingService.getI() == 10;
    }

    @After
    public void destroy(){
        reset(this.list);
    }
}

通配符参数
@RunWith(MockitoJUnitRunner.class)
public class WildcardArgumentMatherTest {

    public class SimpleService {

        public int method1(int i, String s, Collection<?> c, Serializable ss){
            throw new RuntimeException();
        }

        public void method2(int i, String s, Collection<?> c, Serializable ss){
            throw new RuntimeException();
        }
    }

    @Mock
    private SimpleService simpleService;

    @Test
    public void wildcardMethod1(){
        when(simpleService.method1(anyInt(),anyString(),anyCollection(),isA(Serializable.class))).thenReturn(100);
        int result = simpleService.method1(1, "alex", Collections.emptyList(),"Mockito");
        assertThat(result, equalTo(100));
    }

    @Test
    public void wildcarMethod1WithSpec(){
        when(simpleService.method1(anyInt(), eq("alex") ,anyCollection(),isA(Serializable.class))).thenReturn(100);
        when(simpleService.method1(anyInt(), eq("mock") ,anyCollection(),isA(Serializable.class))).thenReturn(200);
        int result = simpleService.method1(1, "alex", Collections.emptyList(),"Mockito");
        assertThat(result, equalTo(100));

        result = simpleService.method1(1, "mock", Collections.emptyList(),"Mockito");
        assertThat(result, equalTo(200));

        result = simpleService.method1(1, "test", Collections.emptyList(),"Mockito");
        assertThat(result, equalTo(0));
    }

    @Test
    public void wildcardMethod2(){
        doNothing().when(simpleService).method2(anyInt(),anyString(),anyCollection(),isA(Serializable.class));
        simpleService.method2(1, "alex", Collections.emptyList(),"Mockito");
        verify(simpleService, times(1)).method2(1, "alex", Collections.emptyList(),"Mockito");
    }
    
    @After
    public void destroy(){
        reset(simpleService);
    }
}

Assert Matcher 使用
import org.junit.Test;
import java.util.stream.Stream;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;

public class AssertMatherTest {

    @Test
    public void test(){
        int i = 10;
        assertThat(i, equalTo(10));
        assertThat(i, not(equalTo(20)));
        assertThat(i, is(10));
        assertThat(i, is(not(20)));
    }

    @Test
    public void test2(){
        double price = 23.45;

        assertThat(price, either(equalTo(23.45)).or(equalTo(23.53)));
        assertThat(price,both(equalTo(23.45)).and(not(23.41)));
        assertThat(price, anyOf(is(23.45),is(32.1)));
        assertThat(price, allOf(is(23.45),not(is(32.1))));

        assertThat(Stream.of(1,2,3).anyMatch(i->i>2),equalTo(true));
        assertThat(Stream.of(1,2,3).allMatch(i->i>0),equalTo(true));
    }
}

自定义Matcher类型
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Factory;

public class GreaterThan<T extends Number>  extends BaseMatcher<T> {

    private final T value;

    public GreaterThan(T value){
        this.value = value;
    }

    @Override
    public boolean matches(Object actual) {

        Class<?> clazz = actual.getClass();
        if(clazz == Integer.class){
            return (Integer)actual > (Integer) value;
        } else if(clazz == Short.class){
            return (Short)actual > (Short) value;
        }else if(clazz == Long.class){
            return (Long)actual > (Long) value;
        } else {
            throw new AssertionError("The number type " + clazz + " not supported");
        }
    }

    @Factory
    public static <T extends Number> GreaterThan<T> gt(T value){
        return new GreaterThan<>(value);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("Compare two number failed");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值