我还有最后一节课,大概是这样的:

public final class RainOnTrees{

   public void startRain(){

        // some code here
   }
}

我在其他一些类中使用这个类,像这样:

public class Seasons{

   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain(){

        rain.startRain();

    }
}

在我的JUnit测试类Seasons.java中,我想模拟RainOnTrees类。我怎么能用Mockito做到这一点?


当前回答

在Mockito 3和更多的我有同样的问题,并修复它从这个链接

模拟最终类和方法与Mockito 依下列各项

在Mockito用于模拟最终类和方法之前,需要对它进行>配置。 我们需要在项目的src/test/resources/mockito-extensions目录中添加一个名为org.mockito.plugins.MockMaker的文本文件,并添加一行文本: mock-maker-inline Mockito在加载时检查扩展目录中的配置文件。该文件允许模拟final方法和类。

其他回答

是的,同样的问题在这里,我们不能模拟一个最终类与Mockito。准确地说,Mockito不能模仿/监视以下内容:

最后的课程 匿名类 原始类型

但是在我看来,使用包装器类代价很大,所以改用PowerMockito。

Mockito 2现在支持final类和方法!

但就目前而言,这只是一个“孵化”功能。它需要一些步骤来激活它,这些步骤在Mockito 2中的新内容中描述:

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.MockMaker containing 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!

你不能用Mockito模拟最后一个类,因为你自己不能这样做。

我所做的是创建一个非final类来包装final类并作为委托使用。一个例子是TwitterFactory类,这是我的mockable类:

public class TwitterFactory {

    private final twitter4j.TwitterFactory factory;

    public TwitterFactory() {
        factory = new twitter4j.TwitterFactory();
    }

    public Twitter getInstance(User user) {
        return factory.getInstance(accessToken(user));
    }

    private AccessToken accessToken(User user) {
        return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
    }

    public Twitter getInstance() {
        return factory.getInstance();
    }
}

缺点是有很多样板代码;好处是您可以添加一些可能与您的应用程序业务相关的方法(如在上面的例子中,getInstance接受用户而不是accessToken)。

在你的例子中,我会创建一个非最终的RainOnTrees类,它委托给最终的类。或者,如果你能让它变成非最终结果,那就更好了。

我来跟进一下。请将这一行添加到您的gradle文件:

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

我尝试了不同版本的mockito-core和mockito-all。他们都不工作。

我正在编写我在Java 11中模拟final/private类及其方法的各种失败尝试之后所遵循的步骤,这些尝试最终对我有用。

在里面创建一个名为org.mockito.plugins.MockMaker的文件 您的test/resources/mockito-extensions文件夹。请创建 Mockito-extensions文件夹(如果还没有)。 在上面的org.mockito.plugins.MockMaker文件中添加一行mock-maker-inline内容 添加

@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "jdk.internal.reflect.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*"})
@PrepareForTest(Utility.class)

类级别的注释。

在测试类中设置过程

  @Before
  public void setup () {
    MockitoAnnotations.initMocks(this);
    Mockito.mockStatic(ClassToBeMocked.class); 
  }

使用Mockito.when(..).thenReturn(..)进行断言 在多个测试用例的情况下,添加下面的代码

  @After
  public void after() {
        Mockito.framework().clearInlineMocks();
  }

我正在使用的模拟版本:3.9.0 Java版本:11