我正在使用Java 6和Mockito 1.8.5。我想模拟一个类'成员字段的方法,但我无法弄清楚如何。我有这些课程......
public class CacheService implements CacheCallback {
private final Cache cache;
...
public static CacheService getInstance() {
return INSTANCE;
}
private CacheService() {
cache = new DefaultCacheImpl();
}
public boolean saveNodes(final Map<Long, XmlNode> nodeMap) {
...
cache.saveNodes(nodeMap);
}
...
}
public class DefaultCacheImpl implements Cache {
...
public void saveNodes(Map<Long, XmlNode> xmlNodes) {
dao.updateDB(xmlNodes);
}
...
}
我无法弄清楚如何模拟“缓存”成员字段的方法“saveNodes”。我正在嘲笑下面的方法,但因为该字段的CacheService类中没有setter,我无法弄清楚如何注入我的模拟..
public class PopulateCacheServiceImpl extends RemoteServiceServlet implements PopulateCacheService {
...
public Boolean initCache() {
boolean ret = false;
try {
setupMocks();
CacheService.getInstance().startCache();
PopulateCache.addTestEntriesToCache();
ret = true;
} catch (Exception e) {
e.printStackTrace(System.err);
ret = false;
} // try
return ret;
} // initCache
private void setupMocks() {
DefaultCacheImpl cache = mock(DefaultCacheImpl.class);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(cache).saveNodes(Matchers.anyMap());
} // setupMocks
}
Mockito有没有其他方法可以做到这一点?谢谢, - 戴夫
答案 0 :(得分:3)
问题出在这一行:
cache = new DefaultCacheImpl();
如果在CacheService中构造一个缓存对象,它们是紧密耦合的。您不能将CacheService与另一个缓存实现一起使用。
相反,将缓存实现传递给构造函数:
public CacheService(Cache cacheImpl) {
this.cache = cacheImpl;
}
这允许CacheService使用任何Cache实现。
答案 1 :(得分:2)
制作两个构造函数怎么样?你拥有的那个会留在那里。另一个允许您传递Cache实现并允许您测试该类。新构造函数可以具有受保护的访问权限,以限制哪些类可以使用它。
答案 2 :(得分:1)
如果您可以更改源代码,请对这些类进行decopule。从Sjoerd建议的构造函数中删除cache = new DefaultCacheImpl();
。
如果你不能 - 将PowerMock用于DefaultCacheImpl
的{{3}}。我必须说这是一个非常丑陋的解决方案(唯一丑陋的是模拟静态初始化代码)。
注意: 您的代码是流行问题“为什么我需要依赖注入?”的答案。我认为人们在发明DI时会看到这样的代码。