<dependency>
<groupId>org.mockitogroupId>
<artifactId>mockito-allartifactId>
<version>2.0.2-betaversion>
dependency>
- mock为一个interface提供一个虚拟的实现,
- spy为object加一个动态代理,实现部分方法的虚拟化
### 正常的bean声明
<bean id=”svc” class=”Svc”>
<bean id=”dao1” class=”…”>
<bean id=”dao2” class=”…”>
<bean id="operationService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.paincupid.api.operation.OperationService" />
bean>
请注意到svc不变化,mock将自动注入进入。这是因为spring的bean容器,如果id一样,后声明的bean会覆盖前面的bean。
<bean id="daoInst" class="DaoInstance">bean>
<bean id="dao2" class="org.mockito.Mockito" factory-method="spy">
<constructor-arg ref="daoInst">constructor-arg>
bean>
同样svc不变化,直接注入。请注意spy需要获得一个实例。
package com.paincupid.springmvc.mybaitsgenerator.persistence.test;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import com.paincupid.springmvc.base.JUnitDaoBase;
import com.paincupid.springmvc.finance.domain.Finance;
import com.paincupid.springmvc.finance.persistence.FinanceMapper;
import com.paincupid.springmvc.finance.service.FinanceService;
public class FinanceServiceTest extends JUnitDaoBase{
@InjectMocks
FinanceService service;
@Mock
FinanceMapper mapper;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void selectByExampleTest() {
Finance f = Mockito.mock(Finance.class);;
f.setBak("bak");
f.setConsumer("consumer");
String id = "1";
Mockito.when(mapper.searchFinanceById(id)).thenReturn(f);
Finance returnF = service.searchFinanceById(id);
Mockito.verify(mapper).searchFinanceById(id);
Assert.assertEquals(f.getConsumer(), returnF.getConsumer());
}
}
package com.paincupid.springmvc.base;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringJUnit4ClassRunner.class)
//使用classpath,会自动去class下的目录去找,所以暂时把它放到了resource目录下。
@ContextConfiguration(locations = {"classpath:/junitTestContext.xml"})
@Transactional
public class JUnitDaoBase extends AbstractTransactionalJUnit4SpringContextTests {
}
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
"
default-lazy-init="true">
<context:component-scan base-package="com.paincupid.springmvc.*.service,com.paincupid.springmvc.*.persistence" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonHttpMessageConverter" />
list>
property>
bean>
<bean id="jsonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8value>
list>
property>
bean>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lee" />
<property name="username" value="lee" />
<property name="password" value="eee" />
<property name="maxConnectionsPerPartition" value="30" />
<property name="minConnectionsPerPartition" value="10" />
<property name="partitionCount" value="1" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage"
value="com.paincupid.springmvc.system.domain,com.paincupid.springmvc.test.domain
,com.paincupid.springmvc.finance.domain" />
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.paincupid.springmvc.*.persistence" />
bean>
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
scope="singleton">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="add*" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="update*" isolation="READ_COMMITTED" rollback-for="Exception" />
<tx:method name="delete*" isolation="READ_COMMITTED" rollback-for="Exception" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.paincupid.springmvc.*.service.*.*(..))" id="pointCut" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut" />
aop:config>
beans>
验证调用次数
verify(mock1, timeout(100).times(2)).get(anyInt());
除了代码中的方法,Mockito 还提供了
- never() 没有被调用,相当于times(0)
- atLeast(N) 至少被调用N次
- atLeastOnce() 相当于atLeast(1)
- atMost(N) 最多被调用N次
超时验证
通过 timeout 我们可以进行验证程序执行时间是否符合规则。
方法调用顺序
Inorder 可以验证方法调用的顺序
verifyNoMoreInteractions 和 verifyZeroInteractions
verifyNoMoreInteractions:查询是否存在被调用,但未被 verify 验证的方法
verifyZeroInteractions:verifyZeroInteractions
ArgumentCaptor 参数捕获器
可在验证时对方法的参数进行捕获,最后验证捕获的参数值。如果方法有多个参数都要捕获验证,那就需要创建多个ArgumentCaptor对象处理。
https://git.oschina.net/paincupid/springmvc.git
http://blog.csdn.net/paincupid/article/details/53561435