单元测试静态方法

时间:2018-12-10 10:35:20

标签: java unit-testing testing static mockito

我正在尝试为此处的解密方法编写一个测试用例。

    private static Codec codec;

    static {
        try {
            codec = new Codec(encryptionType, encryptionKey, false, true, false);
        } catch (CodecException e) {
            throw new RuntimeException("Codec initialisation failed", e);
        }
    }


    public static String decrypt(final String toDecrypt) throws CodecException {
        String decrypted = codec.decryptFromBase64(toDecrypt);
        if (decrypted.endsWith(":")) {
            decrypted = decrypted.substring(0, decrypted.length() - 1);
        }
        return decrypted;
    }

测试用例:

    @Mock
    private Codec codec;
    @Test
    public void test_decrypt_Success() throws CodecException {
        when(codec.decryptFromBase64(TestConstants.toDecrypt)).thenReturn(TestConstants.decrypted);
        assertEquals(DocumentUtils.decrypt(TestConstants.toDecrypt), TestConstants.decrypted);
    }

由于这是一个静态方法,因此我无法在测试套件中注入该类的实例并模拟其编解码器。上面的代码按预期从assert处的编解码器库引发错误。

您测试这种静态方法的方法是什么?还是我根本不应该为此编写测试?

3 个答案:

答案 0 :(得分:3)

在Java中,静态方法并非旨在设置依赖项。
因此,将依赖关系转换为模拟实际上是不自然的。
您可以为以下字段提供static设置器:

private static Codec codec;
public static void setCodec(Codec codec){
   this.codec = codec;
}

您可以使用setCodec(...)来设置模拟,但是嗯...

但是,算了,做得好:重构代码以删除所有静态变量,并引入一个设置编解码器的构造函数。

private Codec codec;
public MyClassUnderTest(Codec codec){
   this.codec codec;
}

IOC可以帮助使被测类成为单例并简化依赖项注入。
如果无法解决,Java 5枚举至少可以帮助您解决单例问题。

答案 1 :(得分:2)

有许多不同的捷径可以达到相同的目的(如评论和其他答案中指出的),但从长远来看,并不是所有的方法都是好的。

我建议创建一个实现Decrypt功能的Singleton类。因此,您将不必创建多个实例,也不需要真正地使用静态方法进行解密,并且可以一次又一次轻松地注入编解码器(我假设您没有多种类型的编解码器,根据您的意见。但是,如果您这样做,则功能应作相应调整)。

有关更多参考:Why use a singleton instead of static methods?

有关为什么应谨慎使用static的参考: Why are static variables considered evil?

答案 2 :(得分:0)

根据我的经验,我只是使用@Before方法准备所有实例:

private Codec codec;

@Before
public void setup() throws CodecException {
  codec = new Codec(encryptionType, encryptionKey, false, true, false);
}