当前位置: 首页 > 知识库问答 >
问题:

Mockito将mock注入间谍对象

段干帅
2023-03-14

我正在为一个具有2级依赖注入的类编写一个测试用例。我对1级依赖项注入对象使用@Spy注释,我想模拟第2级注入。但是,我在第二级上不断遇到空指针异常。有没有办法将模拟注入@Spy对象?

public class CarTestCase{
    @Mock
    private Configuration configuration;

    @Spy 
    private Engine engine;

    @InjectMocks 
    private Car car;

    @Test
    public void test(){

       Mockito.when(configuration.getProperties("")).return("Something");
       car.drive();
    }

}

public class Car{
    @Inject
    private Engine engine;

    public void drive(){
        engine.start();
    }
}

public class Engine{
    @Inject 
    private Configuration configuration;

    public void start(){
        configuration.getProperties();   // null pointer exception
    }

}

共有3个答案

宇文育
2023-03-14

对我有效的(最简单的)解决方案

@InjectMocks
private MySpy spy = Mockito.spy(new MySpy());

在这种情况下,不需要MockitoAnnotations.initMocks(this),只要测试类被注释为@RunAnd(MockitoJUnitRunner.class)

萧嘉禧
2023-03-14

Mockito不能执行如此棘手的注入,因为它不是一个注入框架。因此,您需要重构代码,使其更具可测试性。通过使用构造函数注入很容易完成:

public class Engine{
    private Configuration configuration;

    @Inject 
    public Engine(Configuration configuration) {
        this.configuration = configuration;
    }
    ........
}

public class Car{
    private Engine engine;

    @Inject    
    public Car(Engine engine) {
        this.engine = engine;
    }
}

在这种情况下,您必须手动处理模拟和注入:

public class CarTestCase{

    private Configuration configuration;

    private Engine engine;

    private Car car;

    @Before
    public void setUp(){
        configuration = mock(Configuration.class);
        engine = spy(new Engine(configuration));
        car = new Car(engine);
    }

    @Test
    public void test(){

       Mockito.when(configuration.getProperties("")).return("Something");
       car.drive();
    }

}
章誉
2023-03-14

我还研究了如何向间谍中注入模拟。

以下方法将不起作用:

@Spy
@InjectMocks
private MySpy spy;

但是,当同时使用注释和手动模拟时,可以通过“混合”方法实现所需的行为。以下方法非常有效:

@Mock
private NeedToBeMocked needToBeMocked;

@InjectMocks
private MySpy mySpy;

@InjectMocks
private SubjectUnderTest sut;

@BeforeMethod
public void setUp() {
    mySpy = Mockito.spy(new MySpy());
    MockitoAnnotations.initMocks(this);
}

SubjectUnderTest此处取决于mypy,而mypy则取决于需要删除的内容)。

UPD:就个人而言,我认为如果你不得不经常做这样的事情,这可能是一个迹象,表明你的类之间的依赖性有问题,值得进行一点重构来改进你的代码。

 类似资料:
  • 当我试图在单元测试中窥探一个对象时,我得到了一个异常。这是我的单元测试文件: 我在assign bookInfoParams Spy链接处遇到异常:

  • 我试图用Mockito mock对象替换对象。通常的方法是使用Springockito使用xml: 目前,我正在尝试使用Spring的JavaConfig来完成这项工作。突然之间,Java表达式比xml要详细得多: 我发现了一个名为Springockito annotations的库,它允许您执行以下操作: 显然,更漂亮:)唯一的问题是,这个上下文加载器不允许我对其他bean使用和JavaConf

  • Mockito——我知道间谍在对象上调用实际方法,而模拟在双对象上调用方法。此外,除非有代码气味,否则要避免间谍。然而,间谍是如何工作的?我应该在什么时候使用他们?它们与模拟有什么不同?

  • 问题内容: 我有内部类的课程,如下所示: 模仿测试如下所示:build.gradle: 测试: 第一次测试正在按预期方式工作。第二个永远不会被检测为“已调用”,尽管在日志中我看到的是。有什么问题吗?:) 谢谢! 问题答案: 怎么了? 好吧,这里的问题非常微妙,当您调用时,会在实例背后创建某种装饰器,以允许监视实例上的所有方法调用。因此,您可以检查给定方法被调用了多少次, 但是在装饰器 上 却 没有

  • 有什么建议吗?我如何让Mockito正确地将一个mock注入到一个接口私有字段?

  • 我正在为类编写一个单元测试,该类如下所示: 我想编写一个简单的单元测试,它将方法存根(这样它就不会实际触发并命中数据库),但它允许我验证调用是否最终执行。Mockito似乎是这份工作的合适工具。 这似乎是一个很好的游戏计划(至少对我来说)。但当我实际编写代码时,在测试方法的第2行(行)出现以下编译器错误: 类型Mockito中的(T)不适用于参数(void)时的方法 我看到Mockito无法模拟返