如何使用JUnit中的公共方法将私有字段设置为提供的值?

时间:2017-06-05 07:53:22

标签: java junit4

我有一个班级:

public class MyEncryptor {

    private StringEncryptor stringEncryptor; // this is an interface ref

    public void setStringEncryptor(StringEncryptor stringEncryptorImpl) {

        if(condition){
            this.stringEncryptor = stringEncryptorImpl;
        }

    }
}

在JUnit中测试方法setStringEncryptor时,我想测试实例值stringEncryptor是否设置为我在参数中提供的实现值?或者我采用了错误的方法来测试这种方法?

以下是我在junit测试方法中失败的尝试:

MyEncryptor decryptor = new MyEncryptor ();

        StringEncryptor spbe = new StandardPBEStringEncryptor();
        decryptor.setStringEncryptor(spbe);

        Field f = MyEncryptor .class.getDeclaredField("stringEncryptor");
        f.setAccessible(true);

        Assert.assertSame(f, spbe);

我想测试stringEnctyptor在junit中设置为spbe

3 个答案:

答案 0 :(得分:1)

您提供的单元测试失败,因为您尝试使用Field比较StandardPBEStringEncryptor实例和assertSame实例。你应该做的是:assertSame(f.get(decryptor), StandardPBEStringEncryptor)

请注意,我们使用Field::get方法检索字段的值,我们给出的参数是我们要检索其字段值的实例。

然而,无论如何,单元测试setter类型方法是多余的,只是无缘无故地添加额外的测试代码和测试时间。

答案 1 :(得分:0)

在此断言java.lang.reflect.Field stringEncryptor与您为测试创建的StringEncryptor对象相同的对象:

StringEncryptor spbe = new StandardPBEStringEncryptor();
...
Field f = MyEncryptor .class.getDeclaredField("stringEncryptor");
f.setAccessible(true);
Assert.assertSame(f, spbe);

这是两个截然不同且没有相关类别的两个不同对象 您应该首先检索与该字段关联的值:

 Object value = f.get(spbe);

然后比较对象:

Assert.assertSame(value, spbe);

但无论如何我不认为这是好方法 要测试代码,实现应该是可测试的 只有在我们真的没有选择时,才应该进行反射来测试代码 测试代码的一种自然方法是提供获取实际StringEncryptor字段的方法。

public StringEncryptor getStringEncryptor(){
     return stringEncryptor;
}

通过这种方式,您可以直接断言字段值。

答案 2 :(得分:0)

  

我想测试实例值stringEncryptor是否设置为我的   作为实现参数提供?或者我走错了路   用于测试此方法?

我认为你走错了路。只要有可能,我会测试被测单元是否按预期进行加密,而不是特别设置私有字段。你真的想测试单元功能,而不是它的实现细节。