用 mockito 模拟单例

Mocking a singleton with mockito(用 mockito 模拟单例)
本文介绍了用 mockito 模拟单例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我需要测试一些在方法调用中使用单例的遗留代码.测试的目的是确保类 sunder 测试调用单例方法.我在 SO 上看到过类似的问题,但所有答案都需要其他依赖项(不同的测试框架)——不幸的是,我仅限于使用 Mockito 和 JUnit,但使用这种流行的框架应该是完全可能的.

I need to test some legacy code, which uses a singleton in a a method call. The purpose of the test is to ensure that the clas sunder test makes a call to singletons method. I have seen similar questions on SO, but all the answers require other dependencies (different test frameworks) - I'm unfortunately limited to using Mockito and JUnit, but this should be perfectly possible with such popular framework.

单身人士:

public class FormatterService {

    private static FormatterService INSTANCE;

    private FormatterService() {
    }

    public static FormatterService getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new FormatterService();
        }
        return INSTANCE;
    }

    public String formatTachoIcon() {
        return "URL";
    }

}

被测类:

public class DriverSnapshotHandler {

    public String getImageURL() {
        return FormatterService.getInstance().formatTachoIcon();
    }

}

单元测试:

public class TestDriverSnapshotHandler {

    private FormatterService formatter;

    @Before
    public void setUp() {

        formatter = mock(FormatterService.class);

        when(FormatterService.getInstance()).thenReturn(formatter);

        when(formatter.formatTachoIcon()).thenReturn("MockedURL");

    }

    @Test
    public void testFormatterServiceIsCalled() {

        DriverSnapshotHandler handler = new DriverSnapshotHandler();
        handler.getImageURL();

        verify(formatter, atLeastOnce()).formatTachoIcon();

    }

}

这个想法是配置可怕的单例的预期行为,因为被测试的类将调用它的 getInstance 和 formatTachoIcon 方法.不幸的是,这失败并显示错误消息:

The idea was to configure the expected behaviour of the dreaded singleton, since the class under test will call it's getInstance and then formatTachoIcon methods. Unfortunately this fails with an error message:

when() requires an argument which has to be 'a method call on a mock'.

推荐答案

你的问题是不可能的,因为你的遗留代码依赖于一个静态方法 getInstance() 而 Mockito 不允许模拟静态方法,所以下面这行不起作用

What you are asking is not possible because your legacy code relies on a static method getInstance() and Mockito does not allow to mock static methods, so the following line won't work

when(FormatterService.getInstance()).thenReturn(formatter);

解决这个问题有两种方法:

There are 2 ways around this problem:

  1. 使用允许模拟静态方法的不同模拟工具,例如 PowerMock.

  1. Use a different mocking tool, such as PowerMock, that allows to mock static methods.

重构你的代码,让你不依赖静态方法.我能想到的实现这一点的侵入性最小的方法是向 DriverSnapshotHandler 添加一个构造函数,该构造函数注入一个 FormatterService 依赖项.此构造函数将仅在测试中使用,您的生产代码将继续使用真正的单例实例.

Refactor your code, so that you don't rely on the static method. The least invasive way I can think of to achieve this is by adding a constructor to DriverSnapshotHandler that injects a FormatterService dependency. This constructor will be only used in tests and you production code will continue to use the real singleton instance.

public static class DriverSnapshotHandler {

    private final FormatterService formatter;

    //used in production code
    public DriverSnapshotHandler() {
        this(FormatterService.getInstance());
    }

    //used for tests
    DriverSnapshotHandler(FormatterService formatter) {
        this.formatter = formatter;
    }

    public String getImageURL() {
        return formatter.formatTachoIcon();
    }
}

那么,你的测试应该是这样的:

Then, your test should look like this :

FormatterService formatter = mock(FormatterService.class);
when(formatter.formatTachoIcon()).thenReturn("MockedURL");
DriverSnapshotHandler handler = new DriverSnapshotHandler(formatter);
handler.getImageURL();
verify(formatter, atLeastOnce()).formatTachoIcon();

这篇关于用 mockito 模拟单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Show progress during FTP file upload in a java applet(在 Java 小程序中显示 FTP 文件上传期间的进度)
How to copy a file on the FTP server to a directory on the same server in Java?(java - 如何将FTP服务器上的文件复制到Java中同一服务器上的目录?)
FTP zip upload is corrupted sometimes(FTP zip 上传有时会损坏)
Enable logging in Apache Commons Net for FTP protocol(在 Apache Commons Net 中为 FTP 协议启用日志记录)
Checking file existence on FTP server(检查 FTP 服务器上的文件是否存在)
FtpClient storeFile always return False(FtpClient storeFile 总是返回 False)