简体   繁体   English

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

[英]Not able to Mock Java method call using Spock

I am trying to mock my following java method using Spock.我正在尝试使用 Spock 模拟我的以下 java 方法。


        public List<DiffEntry> listDifferences(String oldCommit, String newCommit, Git git)
          throws GitAPIException, RevisionSyntaxException, AmbiguousObjectException,
          IncorrectObjectTypeException, IOException {

        logger.info(
            "Inside DiffCommits#listDifferences to calculating difference commits refs {}  and {} ",
            oldCommit, newCommit);

        ObjectId oldTree = git.getRepository().resolve(oldCommit);
        ObjectId newTree = git.getRepository().resolve(newCommit);

        if (oldTree == null || newTree == null) {
          logger.warn(
              "Could not resolve either old {} or new commits {}, difference cant not be calculated",
              oldCommit, newCommit);
          throw new RefNotFoundException("Unable to resolve tag reference. Invalid tag provided");
        }

        ObjectReader reader = git.getRepository().newObjectReader();
        CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
        oldTreeIter.reset(reader, oldTree);

        CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
        newTreeIter.reset(reader, newTree);

        DiffFormatter df = new DiffFormatter(new ByteArrayOutputStream());

        df.setRepository(git.getRepository());
        List<DiffEntry> entries;
        entries = df.scan(newTreeIter, oldTreeIter);
        df.close();

        if (logger.isDebugEnabled()) {
          for (int i = 0; i < entries.size(); i++) {
            logger.debug("Entry: " + entries.get(i));
          }
        }

        return entries;
      }

Everything is working fine but the mocking of following code get failed一切正常,但模拟以下代码失败

DiffFormatter df = new DiffFormatter(new ByteArrayOutputStream());

And getting error at并在

df.setRepository(git.getRepository());

The error that I am getting is我得到的错误是

> 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)

Any kind of help will be appreciated任何形式的帮助将不胜感激

DiffFormatter df = new DiffFormatter(new ByteArrayOutputStream());

This code is problematic from the point of view of unit testing.从单元测试的角度来看,这段代码是有问题的。 Its not a dependency so it can't be injected in the class.它不是依赖项,因此不能注入到类中。 So basically you're trying to mock a constructor ( new ) object.所以基本上你试图模拟一个构造函数( new )对象。

Technically the only way you can try is using Global Mocks and create spies wrapping the real object: Read the documentation .从技术上讲,您可以尝试的唯一方法是使用 Global Mocks 并创建包裹真实对象的间谍:阅读文档 These are not regular spock's Mocks and Stubs.这些不是普通的 spock 的 Mocks 和 Stubs。

However I believe there are other approaches.不过我相信还有其他方法。 After all the link I've sent you starts with "think twice before using..." for a reason ;)毕竟我发送给您的所有链接都以“使用前请三思...”开头,这是有原因的;)

  1. You've by yourself decided to put this object creation inside the method, which is ok.您自己决定将此对象创建放在方法中,这是可以的。 However this means that you do not treat this DiffFormatter as a real dependency.但是,这意味着您不会将此DiffFormatter视为真正的依赖项。 So maybe even in unit test you should let it run, concentrating on mocking its input parameters themselves?所以也许即使在单元测试中你也应该让它运行,专注于模拟它的输入参数本身? Just the same holds also for ByteArrayOutputStream . ByteArrayOutputStream也是如此。 This plays nicely in general with the concept that the code should be written in a way that unit tests should not really care about the internal implementation of the methods.这与代码应该以一种单元测试不应该真正关心方法的内部实现的方式编写的概念一起很好地发挥了作用。 Always prefer blackbox testing to white-box testing.总是喜欢黑盒测试而不是白盒测试。

  2. Alternatively if you think its a dependency, then maybe you should make it a data field.或者,如果您认为它是一个依赖项,那么也许您应该将其设为数据字段。 Then You could inject it into the test with a regular mocks.然后您可以使用常规模拟将其注入测试。 If this class should be created per method invocation, you can inject Supplier<DiffFormatter> and in method just call it's get method, it will act as a factory.如果每个方法调用都应该创建这个类,你可以注入Supplier<DiffFormatter> and in method调用它的 get 方法,它将充当工厂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM