Java 用 Mockito 2 模拟最后一堂课

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40979402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:03:05  来源:igfitidea点击:

Mock final class with Mockito 2

javaunit-testingmockito

提问by Ptiseb

I'm removing Powermock from the project I'm currently working on, so I'm trying to rewrite some existing unitary test only with Mockito (mockito-core-2.2.28).

我正在从我目前正在处理的项目中删除 Powermock,因此我试图仅使用 Mockito (mockito-core-2.2.28) 重写一些现有的单一测试。

When I run the test, I have the following error:

当我运行测试时,出现以下错误:

org.mockito.exceptions.base.MockitoException:

Cannot mock/spy class com.ExternalpackagePath.Externalclass

Mockito cannot mock/spy because :

  • final class

org.mockito.exceptions.base.MockitoException:

无法模拟/间谍类 com.ExternalpackagePath.Externalclass

Mockito 不能模拟/间谍,因为:

  • 最后一节课

I know that this question has already been asked (How to mock a final class with mockito, Mock objects calling final classes static methods with Mockito), but I didn't find the answer I'm looking for.

我知道已经有人问过这个问题(How to mock a final class with mockitoMock objects call final classes static methods with Mockito),但我没有找到我正在寻找的答案。

Here is an extract of my code :

这是我的代码的摘录:

public class MyClassToTest extends TestCase {
    private MyClass myClass;
    @Mock private Externalclass ext;  // This class is final, I would like to mock it

    @Override
    protected void setUp() throws Exception {
        MockitoAnnotations.initMocks(this); // <<<< The exception is thrown here
        ext = Mockito.mock(Externalclass.class);
    }
}

As mentioned in the Mockito documentation (https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2, §Mock the unmockable), I added the org.mockito.plugins.MockMaker file. This is the tree of my project :

正如 Mockito 文档中提到的(https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2,§Mockthe unmockable),我添加了 org.mockito.plugins.MockMaker 文件. 这是我的项目树:

  • project
    • src
      • com.packagePath.myPackage
        • myClass
    • test
      • com.packagePath.myPackage
        • myClassToTest
      • resources
        • mockito-extensions
          • org.mockito.plugins.MockMaker
  • 项目
    • 源文件
      • com.packagePath.myPackage
        • 我的课
    • 测试
      • com.packagePath.myPackage
        • 我的类到测试
      • 资源
        • 模拟扩展
          • org.mockito.plugins.MockMaker

I also tries to put the "resources" directory in "src", in a subdir called "test", but the result is still the same.

我还尝试将“资源”目录放在“src”中,在一个名为“test”的子目录中,但结果仍然相同。

I thought that mocking a final was possible with Mockito v2. Does someone have an idea of what is missing here ?

我认为使用 Mockito v2 可以模拟决赛。有人知道这里缺少什么吗?

Thanks!

谢谢!

采纳答案by Ptiseb

Well, I found what's wrong here, it maybe useful for other people. My project tree is wrong, I put the org.mockito.plugins.MockMaker in a directory "mockito-extension" directly in "src". This is my tree now:

好吧,我发现这里出了什么问题,它可能对其他人有用。我的项目树是错误的,我将org.mockito.plugins.MockMaker 直接放在“src”中的“mockito-extension”目录中。这是我现在的树:

  • projet
    • src
      • com.packagePath.myPackage
        • myClass
      • mockito-extensions
        • org.mockito.plugins.MockMaker
  • test
    • com.packagePath.myPackage
      • myClassToTest
  • 项目
    • 源文件
      • com.packagePath.myPackage
        • 我的课
      • 模拟扩展
        • org.mockito.plugins.MockMaker
  • 测试
    • com.packagePath.myPackage
      • 我的类到测试

回答by Somaiah Kumbera

You seem to have had a classpath issue, just like I did.

您似乎遇到了类路径问题,就像我一样。

Your previous setup would have also worked, but it seems like

您之前的设置也可以,但似乎

project/test/resources

was not in your classpath.

不在你的类路径中。

I had the same issue when I tried to run this with IntelliJ. I simply marked the resources directory as a Test Resources Root and it worked fine. Praise the gods of Mockito!

当我尝试使用 IntelliJ 运行它时,我遇到了同样的问题。我只是将资源目录标记为测试资源根目录,它运行良好。赞美Mockito的神!

回答by tim

Weird that your solution seems to work.
According to their documentation on Githubit says.

奇怪的是,您的解决方案似乎有效。
根据他们在Github上的文档,它说。

Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMakercontaining a single line:

mock-maker-inline

After you created this file, Mockito will automatically use this new engine and one can do :

 final class FinalClass {
   final String finalMethod() { return "something"; }
 }

 FinalClass concrete = new FinalClass(); 

 FinalClass mock = mock(FinalClass.class);
 given(mock.finalMethod()).willReturn("not anymore");

 assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

In subsequent milestones, the team will bring a programmatic way of using this feature. We will identify and provide support for all unmockable scenarios. Stay tuned and please let us know what you think of this feature!

模拟 final 类和方法是一个孵化的、可选的功能。它使用 Java 代理检测和子类化的组合来实现这些类型的可模拟性。由于这与我们当前的机制不同,并且这个机制有不同的限制,并且我们想要收集经验和用户反馈,因此必须明确激活此功能才能使用;它可以通过 mockito 扩展机制通过创建src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker包含一行的文件来完成:

mock-maker-inline

创建此文件后,Mockito 将自动使用这个新引擎,您可以这样做:

 final class FinalClass {
   final String finalMethod() { return "something"; }
 }

 FinalClass concrete = new FinalClass(); 

 FinalClass mock = mock(FinalClass.class);
 given(mock.finalMethod()).willReturn("not anymore");

 assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

在随后的里程碑中,团队将带来使用此功能的编程方式。我们将识别所有不可模拟的场景并提供支持。请继续关注,请让我们知道您对此功能的看法!

My working structure now looks like this.

我的工作结构现在看起来像这样。

enter image description here

在此处输入图片说明

回答by Thomas Keller

I couldn't get it working with the configuration file either; however, the Mockito team is so kind and also provides a pre-configured Mockito artifactthat requires no configuration in the target project.

我也无法使用配置文件;但是,Mockito 团队很善良,还提供了一个预配置的 Mockito 工件,不需要在目标项目中进行配置。

As a convenience, the Mockito team provides an artifact where this mock maker is preconfigured. Instead of using the mockito-core artifact, include the mockito-inline artifact in your project. Note that this artifact is likely to be discontinued once mocking of final classes and methods gets integrated into the default mock maker.

为方便起见,Mockito 团队提供了一个工件,其中预配置了此模拟生成器。不要使用 mockito-core 工件,而是在您的项目中包含 mockito-inline 工件。请注意,一旦对最终类和方法的模拟集成到默认模拟生成器中,此工件可能会停止使用。

So, if you use Gradle and want to test your Kotlin code, just add this to your project's dependencies:

因此,如果您使用 Gradle 并想测试您的 Kotlin 代码,只需将其添加到您项目的依赖项中:

testCompile 'org.mockito:mockito-inline:2.8.9'
testCompile('com.nhaarman:mockito-kotlin:1.5.0') {
    exclude group: 'org.jetbrains.kotlin'
    exclude group: 'org.mockito'
}

回答by S.Javed

This solution worked for me: Instead of

这个解决方案对我有用:而不是

testCompile "org.mockito:mockito-android:2.9.0"

in the gradle file, replace it with

在gradle文件中,将其替换为

testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.9.0' 

and it would work.

它会起作用。

回答by exody

I had the same issue that you described. For me, the solution was to create the org.mockito.plugin.MockMackerfile in /test/java/resources/mockito-extensions/directory and write the following line: mock-maker-inline.

我遇到了你描述的同样问题。对我来说,解决方案是org.mockito.plugin.MockMacker/test/java/resources/mockito-extensions/目录中创建文件并写入以下行:mock-maker-inline.

So MockMaker is actually the file extension (no txt, properties or any other extension needed).

所以 MockMaker 实际上是文件扩展名(不需要 txt、properties 或任何其他扩展名)。

回答by KaMyLL

If you have multiple modules in project check out if they also have some references to Mockito. For me the problem was deprecated and unnecessary definition in some other small and forgotten library module:

如果项目中有多个模块,请检查它们是否也有一些对 Mockito 的引用。对我来说,这个问题在其他一些小而被遗忘的库模块中已被弃用和不必要的定义:

testCompile 'org.mockito:mockito-all:1.10.19'

Removing this unnecessary declaration solved the problem for me

删除这个不必要的声明为我解决了这个问题