无法使用Spock模拟Java方法调用

无法使用Spock模拟Java方法调用,java,spock,Java,Spock,我试图用Spock模拟我下面的java方法 公共列表列表差异(字符串oldCommit、字符串newCommit、Git-Git) 抛出GitAPIException、RevisionSyntaxException、AmbiguousObjectException、, IncorrectObjectTypeException,IOException{ logger.info( “Inside DiffCommissions#listDifferences to Computing differ

我试图用Spock模拟我下面的java方法


公共列表列表差异(字符串oldCommit、字符串newCommit、Git-Git)
抛出GitAPIException、RevisionSyntaxException、AmbiguousObjectException、,
IncorrectObjectTypeException,IOException{
logger.info(
“Inside DiffCommissions#listDifferences to Computing difference Commissions refs{}和{}”,
Oldcomit,newCommit);
ObjectId oldTree=git.getRepository().resolve(oldCommit);
ObjectId newTree=git.getRepository().resolve(newCommit);
if(oldTree==null | | newTree==null){
logger.warn(
“无法解析旧的{}或新的提交{},无法计算差异”,
Oldcomit,newCommit);
抛出新的RefNotFoundException(“无法解析标记引用。提供的标记无效”);
}
ObjectReader=git.getRepository().newObjectReader();
CanonicalTreeParser OldTreeItemer=新CanonicalTreeParser();
重置(读取器,oldTree);
CanonicalTreeParser newtreiter=新CanonicalTreeParser();
重置(读卡器,newTree);
DiffFormatter df=新的DiffFormatter(new ByteArrayOutputStream());
setRepository(git.getRepository());
列出条目;
条目=df.scan(newtreiter、oldTreeIter);
df.close();
if(logger.isDebugEnabled()){
对于(int i=0;i
一切正常,但对以下代码的模拟失败

DiffFormatter df=new DiffFormatter(new ByteArrayOutputStream());
并且在

df.setRepository(git.getRepository());
我得到的错误是

> org.eclipse.jgit.lib.StoredConfig$$EnhancerByCGLIB$$9a2f8398 cannot be
> cast to org.eclipse.jgit.diff.DiffConfig java.lang.ClassCastException:
> org.eclipse.jgit.lib.StoredConfig$$EnhancerByCGLIB$$9a2f8398 cannot be
> cast to org.eclipse.jgit.diff.DiffConfig  at
> org.eclipse.jgit.diff.DiffFormatter.setReader(DiffFormatter.java:201)
>   at
> org.eclipse.jgit.diff.DiffFormatter.setRepository(DiffFormatter.java:180)
>   at
> com.sf.bt.mdm.subscription.scmdiff.DiffCommits.listDifferences(DiffCommits.java:65)
>   at com.sf.bt.mdm.subscription.service.DiffCommitSpec.test list
> differences(DiffCommitSpec.groovy:59)
任何形式的帮助都将不胜感激

DiffFormatter df = new DiffFormatter(new ByteArrayOutputStream());
从单元测试的角度来看,这段代码是有问题的。它不是依赖项,因此不能注入类中。所以,基本上你是在模拟一个构造函数(
new
)对象

从技术上讲,您可以尝试的唯一方法是使用全局模拟并创建封装真实对象的间谍:阅读。这些不是斯波克的模拟和存根

不过,我相信还有其他方法。我给你发的所有链接都以“使用前三思而后行”开头,这是有原因的;)

  • 您自己决定将此对象创建放在方法中,这是可以的。但是,这意味着您不会将此
    DiffFormatter
    视为真正的依赖项。所以,也许即使在单元测试中,您也应该让它运行,集中精力模拟它的输入参数本身?同样适用于
    ByteArrayOutputStream
    。这在总体上很好地体现了这样一个概念,即代码应该以单元测试不应该真正关心方法的内部实现的方式编写。总是喜欢黑盒测试而不是白盒测试

  • 或者,如果您认为它是一个依赖项,那么也许您应该将它设置为一个数据字段。然后,您可以使用常规模拟将其注入测试。如果这个类应该在每次方法调用时创建,那么您可以注入
    Supplier,并在方法中调用它的get方法,它将充当工厂


  • 将其传递给方法,或使其成为构造函数传递的类变量。通过这种方式,您可以传递一个mock,您的方法将使用mock。@Bentaye还有其他方法吗?请发布您得到的错误。@Bentaye错误在问题中更新Global mock不适用于测试中的Java代码,仅适用于Groovy代码。根据您的建议,应该重构被测试的类以获得更好的可测试性,从而使依赖项可注入,或者至少将其创建考虑到stubbable helper方法中。否则,必须使用PowerMock之类的工具,这将是一种代码味道。