如何将模拟注入到方法中,距离经过测试的类仅两步之遥

时间:2019-04-20 08:51:37

标签: java spring mockito

我想写一个类和它在操作过程中调用的“下级”类的集成测试。我想模拟“下层”类调用的数据库连接,但是我还没有找到一种方法。

我有一个类,该类调用另一个类,该类通过jdbcTemplate调用数据库。我想将模拟jdbcTemplate注入较低的类,但是我似乎将其注入到该类的错误实例中。该代码遵循以下模板:

@Component
public class A {

    @AutoWired
    B b

    public String someMethod() {
        b.otherMethod();
    }

}


@Component
public class B {

    @AutoWired
    jdbcTemplate jdbctemplate

    public String otherMethod() {
        jdbctemplate.query(args);
    }

}

测试如下:

@RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass { 

    @Mock
    JdbcTemplate jdbcTemplate;

    @InjectMocks
    B b;

    @InjectMocks
    A a;

    @Test
    public void aTest() {
        a.someMethod();
    }
}

但是当我运行此测试时,我在a.someMethod()处收到NullPointerException-似乎被调用的B对象为空。

问题是,如果我模拟B,那么它永远不会真正调用jdbcTemplate,因为它是模拟的。

有人能阐明我如何将模拟jdbcTemplate注入到A调用的B对象吗?

2 个答案:

答案 0 :(得分:3)

如果您要进行实际的集成测试:

1)不要模拟模板。模拟整个存储库。

2)集成测试中不需要@InjectMocks。 Spring做DI。

3)由于这是IT测试,您需要使用SpringRunner.class,而不是MockitoJUnitRunner.class运行器。

@RunWith(SpringRunner.class)
public class aTestClass { 

    @MockBean
    B b;

    @Autowired
    A a;

    @Test
    public void aTest() {
        a.someMethod();
    }
}

对于单元测试,只需模拟B并注入A:

@RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass { 

    @Mock
    B b;

    @InjectMocks
    A a;

    @Test
    public void aTest() {
        a.someMethod();
    }
}

请勿在单元测试中模拟依赖项的依赖项。您不应该关心那里的较低级别。

答案 1 :(得分:0)

在DuckDuck进行了一段时间之后,我设法使测试与Maciejs指令一起使用。最初,它不起作用,但是将@Configuration添加到了它同时起作用的两个bean中。这是对我有用的代码:

@RunWith(SpringRunner.class)
public class aTestClass { 

    @MockBean
    JdbcTemplate jdbcTemplate;

    @Autowired
    B b;

    @Autowired
    A a;

    @Test
    public void aTest() {
        when(jdbcTemplate.query(args)).thenAnswer(whatyouwant));
        a.someMethod();
    }

    @Configuration
    @Import(A.class)
    static class AConfig {
    }

    @Configuration
    @Import(B.class)
    static class BConfig {
    }

}