Mockito介绍和使用

Mockito介绍和使用

一、什么是mockito? mockito有什么作用?
Mockito是一个mocking框架,让你用简单干净的API写漂亮的测试代码。Mockito不会让你混乱,因为测试代码具有非常好的可读性,Mockito可以创建纯净的环境来进行代码功能的验证。

Mockito介绍和使用_第1张图片

如上图所示,ServiceA中的Func1调用了另外一个ServiceB里的Func2以及Dao层1和2两个类中的CRUD的方法,如果我们想对ServiceA进行单元测试,首先需要把serviceB和Dao1,Dao2三个类的实例构建出来,并且在测试ServiceA的Func1时,肯定会执行ServiceB中的Func2和Dao1和2两个类中的CRUD的方法,如果这三个方法中出错,也会导致我们的单元测试异常,这不是我们的本意,我们只需要测试ServiceA中的Func1功能是否正确,另外的三个方法有专门的测试类会对他们进行测试。由此,我们引入了mockito框架。

Mockito介绍和使用_第2张图片

mock对象就是在调试期间用来作为真实对象的替代品。
Mockito 是用于生成模拟对象或者直接点说,就是”假对象“的工具。一般通常的做法就是联合 JUnit + Mockito 来进行测试。

二、简单使用
Maven依赖:

<dependency>  
    <groupId>org.powermockgroupId>  
    <artifactId>powermock-api-mockitoartifactId>  
    <version>1.6.5version>  
    <scope>testscope>  
dependency>         
<dependency>  
    <groupId>org.powermockgroupId>
    <artifactId>powermock-module-junit4artifactId>  
    <version>1.6.5version>  
    <scope>testscope>  
dependency>  

Java代码:

import static org.mockito.Mockito.*;

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();

三、更多…

  • mock()/@Mock: 在需要Mock的属性上标记@Mock注解,然后@RunWith(MockitoJUnitRunner.class)或者在@Before方法中显示调用MockitoAnnotations.initMocks(this);生成Mock类即可
  • spy()/@Spy: 部分的mocking,@Mock是针对接口生成Mock类,所以我们是没法调用到真实的实现类的方法。可以使用@Spy注解标注属性,并且标注@Resource注解让Spring注入真实实现类,那么Mockito就会自动生成Spy类。Spy类就可以满足我们的要求。如果一个方法mock了返回值或者异常,那么就会按照mock的方式被调用执行;如果一个方法没被mock,那么调用的就是真实类的方法。
  • @InjectMocks: 自动的将带有@Mock和@Spy注解的属性注入到被测试类中
  • verify(): 检查方法是否被调用
  • 参数匹配器:Matchers类内加了有很多参数匹配器anyInt(),anyString(),anyMap()…..Mockito类继承于Matchers,Stubbing时使用内建参数匹配器。如果使用参数匹配器,那么所有的参数都要使用参数匹配器,不管是stubbing还是verify的时候都一样。

四、复杂示例

  1. Dao层
@Repository
public class OrderDao {
    public Order getOrder(int irderId){
        throw new UnsupportedOperationException("Fail is not mocked!");
    }
}

2.Service层

@Service
public class PriceService {
    public int getActualPrice(Item item){
        throw new UnsupportedOperationException("Fail is not mocked!");
    }

    public int calculatePriceForOrder(Order order){
        int orderPrice = 0;
        for (Item item : order.getItems()){
            orderPrice += getActualPrice(item);
        }
        return orderPrice;
    }
}
@Service
public class OrderService {

    @Autowired
    private PriceService priceService;

    @Autowired
    private OrderDao orderDao;

    public int getOrderPrice(int orderId){
        Order order = orderDao.getOrder(orderId);
        return priceService.calculatePriceForOrder(order);
    }
}

3.测试Service类

public class OrderServiceTest {
    private static final int TEST_ORDER_ID = 15;
    private static final int TEST_SHOES_PRICE = 2;  
    private static final int TEST_SHIRT_PRICE = 1;

    @InjectMocks
    private OrderService testingObject;

    @Spy
    private PriceService priceService;

    @Mock
    private OrderDao orderDao;

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

    @Test
    public void testGetOrderService(){
        Order order = new Order(Arrays.asList(Item.SHOES, Item.SHIRT));
        Mockito.when(orderDao.getOrder(TEST_ORDER_ID)).thenReturn(order);

        //notice different Mockito syntax for spy
        Mockito.doReturn(TEST_SHIRT_PRICE).when(priceService).getActualPrice(Item.SHIRT);
        Mockito.doReturn(TEST_SHOES_PRICE).when(priceService).getActualPrice(Item.SHOES);

        //call testing method
        int actualOrderPrice = testingObject.getOrderPrice(TEST_ORDER_ID);

        Assert.assertEquals(TEST_SHIRT_PRICE + TEST_SHOES_PRICE, actualOrderPrice);
    }
}

你可能感兴趣的:(测试)