如何将间谍对象注入私有字段

时间:2019-09-10 12:22:29

标签: java mockito

我正试图在没有运气的情况下将间谍注入到专用域private Map<Integer, IPatron> patrons;中。该字段不属于任何构造函数,也不具有任何setter或getter。我正在尝试避免对源代码进行更改。

如果该字段设置为公开,我可以明确分配间谍,但据我了解,它应该自动发生。


package library;

import java.util.Map;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import library.entities.IPatron;
import library.entities.Library;


@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT) // allows unnecessary "stubbing"
class TestTing{
    @Spy 
    private Map<Integer, IPatron> patrons;

    @Spy
    @InjectMocks
    Library library;

    @BeforeEach
    void setUp(){
    }

    @Test
    void getPatronList(){
        library.getPatronList();
        //someTest
        patrons.size();
    }
}



    private Map<Integer, IPatron> patrons;


    public Library() {

        patrons = new HashMap<>();
    }

    @Override
    public List<IPatron> getPatronList() {      
        return new ArrayList<IPatron>(patrons.values()); 
    }

我的理解是@Spy private Map<Integer, IPatron> patrons;将在被测类中找到private Map<Integer, IPatron> patrons;并将其替换。

2 个答案:

答案 0 :(得分:1)

首先,您正在正确测试类Library,因此它不是间谍或其他任何东西,而只是常规实例,因此您应在测试中像这样创建它:

 Library underTest = new Library(...);

现在,您的问题的答案不是关于Mockito,而是关于使代码可以进行单元测试。

没有任何产生的代码可以自动进行单元测试。

现在编写类Library是不可能的(除非您用反射强行设置顾客)。反思也不是做到这一点的好方法。

我建议使用依赖注入原理并重构代码,如下所示:

class Library {
   private Map<Integer, IPatron> patrons;

   public Library(Map<Integer, IPatron> patrons) {
        this.patrons = patrons;
   }
}

然后在测试中,您可以将patrons创建为地图,间谍,模拟或任何您想要模仿真实互动的内容,然后注入Library

Library underTest = new Library(patrons);

答案 1 :(得分:0)

您在Library类中硬性支持顾客依赖。不要使用硬编码。
我们应该要求依赖而不是自己定义。
我们在构造函数中要求强制性依赖,在setter中要求可选的依赖。
将构造函数的签名更改为以下内容:

public Library(Map<Integer, IPatron> patrons) {
    this.patrons = patrons;
}

还可以让顾客最终确定。

在这种情况下,Library类并不关心创建顾客的方式及其内容。因为这不是它的责任。

您现在不需要任何间谍或嘲笑来测试Library类。而且它更具可扩展性和可测试性。