我正在使用Mockito来测试我的API服务REST,我正在使用Spring Framework 4.1.4.RELEASE和Mockito 1.9.5。
我有一个多品牌系统可以访问独特的DAOImpl(每个品牌都有独特的@PersistenceContext(unitname =“emX”),其中“X”是品牌char),每个品牌都延伸自抽象的DaoBase类(谁的实施)一个名为Dao的接口,我从Service类访问,通过以下方式获取组件:
applicationContext.getBean(qualifier.concat(brand.name()),clazz)
(例如qualifier.concat(brand.name())其=“DaoA”)
这是结构:
- es.app.service
- ServiceClass.java调用DaoFactory来获取Impl。
- es.app.dao
- Dao.java
- DaoBase.java实现Dao
- DaoFactory.java
- es.app.dao.impl
- DaoAImpl.java扩展了DaoBase @Repository(“DaoA”)
- DaoBImpl.java扩展DaoBase @Repository(“DaoB”)
- DaoCImpl.java扩展了DaoBase @Repository(“DaoC”)
- DaoDImpl.java扩展了DaoBase @Repository(“DaoD”)
然后我在测试包上有一个测试类
- es.app.service
ServiceClassTest.java
我在这里为每个课程添加了一些代码:
DaoFactory.java
@Component
public class DaoFactory implements Serializable, ApplicationContextAware{
private ApplicationContext ctx;
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(DaoFactory.class);
public Dao getInstance(GroupBrand brand){
switch(brand){
case A:
case B:
case C:
case D:
return (Dao)getComponent("Dao",Dao.class, brand);
default: break;
}
throw new IllegalArgumentException("Unsupported brand ".concat(brand.name()));
}
private Object getComponent(String qualifier, Class<?> clazz, GroupBrand brand){
Object instance = ctx.getBean(qualifier.concat(brand.name()), clazz);
if(Utils.isNull(instance)){
throw new IllegalArgumentException("Unkown business bean with Qualifier: ".concat(qualifier.concat(brand.name())).concat("type: ").concat(clazz.getName()));
}
LOGGER.debug("DAO retrived: " + qualifier.concat(brand.name()) +" class: " + clazz.getName());
return instance;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx = applicationContext;
}
}
DaoBase.java
public abstract class DaoBase implements Dao {
protected abstract EntityManager getEntityManager();
private static final String EMPTY = "";
private static final Logger LOGGER = LoggerFactory.getLogger(DaoBase.class);
@Override
public Boolean findAvailability(GroupBrand marca, String code) {
EntityManager em = getEntityManager();
Query query = em.createNamedQuery("Conn.isAvailability");
query.setParameter(1, code);
query.setParameter(2, marca.toCharCode());
try{
String value = (String)query.getSingleResult();
if(value.equalsIgnoreCase("S")){
return true;
}else{
return false;
}
}catch(Exception ex){
return Boolean.FALSE;
}
}
}
DaoAImpl.java
@Repository("DaoA")
public class DaoAImpl extends DaoBase {
@PersistenceContext(unitName = "emA")
private EntityManager em;
@Override
@Transactional("A")
public Boolean findAvailability(GroupBrand marca, String code) {
return super.findAvailability(marca, code);
}
}
ServiceClass.java
@Override
public boolean isAvailable(GroupBrand brand, String code){
Boolean available = getDMSQisAvailability(brand, code);
return available;
}
protected Boolean isAvailability(GroupBrand marca, String kvps){
boolean value = daoFactory.getInstance(marca).findDMSQisAvailability(marca, code);
return value;
}
ServiceClassTest.java
@InjectMocks
@Autowired
@Qualifier("serviceClass")
private ServiceClass srv;
@Autowired
@Qualifier("DaoFactory")
protected DaoFactory daoFactory;
@Mock
protected Dao dao;
@Override
public void mockBehaivors() throws ResourceException, ResourceNotFoundException, ApiException {
MockitoAnnotations.initMocks(this);
dao = daoFactory.getInstance(marca);
when(dao.findAvailability(any(GroupBrand.class), any(String.class))).thenReturn(Boolean.TRUE);
}
@Test
public void isAvailableTest() throws ResourceException, Exception{
Boolean available = srv.isAvailable(GroupBrand.A, "CODE");
}
我需要覆盖ServiceClass.java类,但我无法模拟来自此Test类的Dao调用总是进行真正的调用而不返回我在“when”上定义的内容,其他测试有效,但未使用dao访问。
任何人都可以帮助我?
(为我可怜的英语道歉)..
此致
答案 0 :(得分:1)
至少我找到了解决问题的方法,
当调用 getInstance()时,我必须模拟 DaoFactory 我返回 Dao 类的模拟。
类测试它是这样的:
@InjectMocks
@Autowired
@Qualifier("serviceClass")
private ServiceClass srv;
@Mock
@Autowired
@Qualifier("DaoA")
protected Dao dao;
@Mock
@Autowired
@Qualifier("DaoFactory")
protected DaoFactory daoFactory;
@Override
public void mockBehaivors() throws ResourceException, ResourceNotFoundException, ApiException {
MockitoAnnotations.initMocks(this);
when(daoFactory.getInstance(GroupBrand.A)).thenReturn(dao);
when(dao.findAvailability(any(GroupBrand.class), any(String.class))).thenReturn(Boolean.TRUE);
}
@Test
public void isAvailableTest() throws ResourceException, Exception{
Boolean available = srv.isAvailable(GroupBrand.A, "CODE");
}
它的作品!!!!
答案 1 :(得分:0)
尝试在DAO上使用@MockBean(理想情况下@Mock也相同)并进行如下所述的存根。 在测试用例初始化方法上注释@Before并将子句逻辑移动到实际测试用例(我总是这样做)
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTest extends MyServiceImpl {
@Autowired
private MyService myervice;
@MockBean
private MyDAO myDao;
@Before
public void setupMock()
{
MockitoAnnotations.initMocks(this);
}
你可以尝试创建存根以便不调用DAO,如下面的代码片段所示 测试用例。在你的例子中,你已经在测试中完成了它 初始化块
AddressDTO planContactaddressDTO = buildAddressDTO();
//build this stub method buildAddressDTO() to return AddressDTO which your actual DAO will return
when(myDao.saveAddress(addressBO)).thenReturn(addressDTO);