我正在重构一个Hibernate映射对象Gadget
以删除getIntFieldValue
和setIntFieldValue
并更改我的代码以从DAO对象中检索该值,该对象是使用{{1}创建的和小工具通过。
Factory
测试代码如下所示:
public class GadgetPropertyAccessFactory {
public static GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
}
...
//this mocks a Gadget
Gadget gadget = createGadget();
//this is to be replaced
when(gadget.getIntFieldValue()).thenReturn(2);
DoerClass doerClass = new DoerClass(null, gadget);
List<Result> doerResults = doerClass.produceResults();
for (Result doerResult : doerResults) {
//...
}
看起来像这样
DoerClass
我的问题是,在我能够方便地模拟Session dbSessn;
Gadget gadget;
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
//this is to be replaced
int intFieldValue = this.gadget.getIntFieldValue()
//with
//GadgetPropertyDAO gadgPropDAO = GadgetPropertyAccessFactory.getGadgetPropertyDAO(this.dbSessn);
//int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
//generate List<Result> based on intFieldValue
}
将在getIntFieldValue
中返回的内容之前,但现在我正在使用静态返回的DAO,我不知道是否可以模拟produceResults
将返回。
是否可以在不更改方法签名(API)的情况下进行模拟?
答案 0 :(得分:0)
我同意Tom G:Mockito和依赖注入(可以说是Java本身)实际上是为实例设计的,而不是静态方法 - 它是利用Java多态优势的唯一方法。如果切换到使工厂成为实例,它将如下所示:
public class GadgetPropertyAccessFactory {
public GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
} // ...
}
public class DoerClass {
Gadget gadget;
Session dbSessn;
// Sets default implementation. Constructor injection would also work.
GadgetPropertyAccessFactory gpaFactory = new GadgetPropertyAccessFactory();
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
GadgetPropertyDAO gadgPropDAO =
gpaFactory.getGadgetPropertyDAO(this.dbSessn);
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
}
// in your test
DoerClass doerClass = new DoerClass(null, gadget);
GadgetPropertyAccessFactory mockFactory =
Mockito.mock(GadgetPropertyAccessFactory.class);
doerClass.gpaFactory = mockFactory;
// ...
另一种选择是与测试差距一起生存并管理:
public List<Result> produceResults() {
return produceResultsInternal(gpaFactory.getGadgetPropertyDAO(this.dbSessn));
}
/** Visible only for testing. Do not call outside of tests. */
List<Result> produceResultsInternal(GadgetPropertyDAO gadgPropDAO) {
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
...然后允许您使用模拟对produceResultsInternal
进行测试,这样可以让您在80%的测试中获得20%的悲伤。