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

Java 如何将间谍对象注入私有字段,java,mockito,Java,Mockito,我正试图把一个间谍注入私人领域私人地图用户;没有运气。该字段不属于任何构造函数,也不具有任何setter或getter。如果可能的话,我会尽量避免对源代码进行更改 如果字段设置为public,我可以显式地分配spy,但据我所知,它应该自动发生 package library; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org

我正试图把一个间谍注入私人领域私人地图用户;没有运气。该字段不属于任何构造函数,也不具有任何setter或getter。如果可能的话,我会尽量避免对源代码进行更改

如果字段设置为public,我可以显式地分配spy,但据我所知,它应该自动发生


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();
    }
}


我的理解是@Spy私人地图的赞助人;将找到私人地图用户;首先,您正在正确测试类库,因此它不是间谍或任何东西,它只是一个常规实例,因此您应该在测试中创建它,如下所示:

 Library underTest = new Library(...);
class Library {
   private Map<Integer, IPatron> patrons;

   public Library(Map<Integer, IPatron> patrons) {
        this.patrons = patrons;
   }
}
现在,您的问题的答案不是关于Mockito,而是关于使代码单元可测试

没有任何生成的代码是自动可单元测试的

因为类库是现在写的,除非你强迫用户进行反思,否则它是不可能的。反思也不是一种很好的方法

我建议使用依赖项注入原则,并按照如下方式重构代码:

 Library underTest = new Library(...);
class Library {
   private Map<Integer, IPatron> patrons;

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

您可以在库类中硬编码用户依赖项。不要使用硬编码。 我们应该要求依赖关系,而不是自己定义它们。 我们在构造函数中要求强制依赖,在setters中要求可选依赖。 将构造函数的签名更改为以下内容:

public Library(Map<Integer, IPatron> patrons) {
    this.patrons = patrons;
}
同时,也要将用户字段设置为最终字段

在这种情况下,Library类不关心用户是如何创建的以及用户是什么。因为这不是它的责任


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

为什么您认为它不起作用?@second在运行时检查字段时显示的是一个香草HashMap对象,而不是mockito注入的HashMap。您使用的mockito版本是什么?当我用v3.0.0验证这一点时,调试向我显示模拟被正确注入,并且您的测试的更完整版本返回了我为模拟指定的结果。-无论如何,执行@MarkBramnik建议的更改是更干净的方法。虽然我同意你的建议,但我只想指出,在执行问题中的代码时,间谍的位置是正确的。无参数构造函数正在执行的任何操作都不会妨碍字段注入。-另外,一般来说,地图不应该被嘲笑或刺探,应该尽可能使用真实的地图。谢谢你的回复。我想我把自己逼到了一个角落,试图变得纯洁。我和我的讲师谈过,他提到对源代码进行一些更改是必要的,以允许对其进行测试。