【问题标题】:How to test when Superclass method is called?如何测试何时调用超类方法?
【发布时间】:2020-10-16 02:00:26
【问题描述】:

我尝试在下面的课程中进行测试,但得到了“org.mockito.exceptions.base.MockitoException: 只有 void 方法可以 doNothing()!”,当我尝试 Mocking 时,我得到了 nullpointerException。

@Configuration

@Profile("cloud")
public class PsqlConfiguration extends AbstractCloudConfig {

    @Bean
    public DataSource dataSource() {
        return connectionFactory().dataSource();
    }
}

笔试 =>

@RunWith(MockitoJUnitRunner.class)
class PsqlConfiguration extends AbstractCloudConfig{

    @Test
    void dataSource() {
        PsqlConfiguration ch = Mockito.spy(new PsqlConfiguration());
        Mockito.doNothing().when((AbstractCloudConfig)ch).connectionFactory();
        ch.dataSource();
    }

模拟测试书面

@RunWith(MockitoJUnitRunner.class)

类 PsqlConfigurationTest {

@InjectMocks
PsqlConfiguration psqlConfiguration = new PsqlConfiguration();

AbstractCloudConfig config = Mockito.mock(AbstractCloudConfig.class);

@Test
void dataSource() {
    DataSource dataSource = Mockito.mock(DataSource.class);
    Cloud cloud = Mockito.mock(Cloud.class);
    ServiceConnectionFactory factory = new CloudServiceConnectionFactory(cloud);
    Mockito.when(config.connectionFactory()).thenReturn(factory);
    System.out.println(config.connectionFactory());
    Mockito.when(config.connectionFactory().dataSource()).thenReturn(dataSource);
    assertNull(psqlConfiguration.dataSource()); // This gives null

}

}

【问题讨论】:

  • 为什么?为什么你还要为你的配置写一个测试并模拟它?无论如何,doNothing 意味着它不会返回任何东西,并且该方法显然应该返回一些东西。所以你可能想返回一个模拟或间谍:baeldung.com/mockito-behavior
  • 我尝试过模拟,但它给出了 Nullpointer 异常。我知道普通模拟,但它对超类的工作方式相同吗?
  • 你能添加这个测试的意图吗?你到底想测试什么?我看不到任何与超类相关的内容
  • 您好,如果我直接模拟子类方法,那么它可以工作,但代码覆盖率为 0%,所以我想模拟“connectionFactory().dataSource()”。所以它给出了 100% 的代码覆盖率,但是它给出了 NullPointerException

标签: java junit5 spring-boot-test


【解决方案1】:

从你的测试来看,我想你想verify() 你的配置的dataSource() 方法正在被调用。如果是这样,您可能想要以下内容:

@Test
void dataSource() {
    PsqlConfiguration ch = Mockito.spy(new PsqlConfiguration());
    DataSource mockDs = Mockito.mock(DataSource.class);
    Mockito.doReturn(mockDs).when(ch).dataSource();
}

您收到错误的原因是AbstractCloudConfig 类的dataSource() 方法返回DataSource,而不是void。您只能使用doNothing() 模拟void 方法。

如果你真的想要模拟超类,你可以这样做:

@Test
void dataSource() {
    PsqlConfiguration ch = Mockito.spy(new PsqlConfiguration());
    DataSource mockDs = Mockito.mock(DataSource.class);
    ConnectionFactory mockFactory = Mockito.mock(ConnectionFactory.class);
    Mockito.doReturn(mockDs).when(ch).dataSource();
    Mockito.doReturn(mockFactory).when((AbstractCloudConfig)ch).connectionFactory();
    ch.dataSource();
    verify(ch).connectionFactory();
}

但是请注意,这个测试在编写时是没有意义的。您的配置类不会执行任何不是来自您的框架的代码(就您编写的而言,并且配置是由 Spring 加载的)。测试应该只测试你自己的代码,而不是底层框架(它有自己的测试)。


我看到你的评论:

如果我直接模拟子类方法,那么它可以工作,但代码覆盖率为 0%,所以我想模拟“connectionFactory().dataSource()”。所以它给出了 100% 的代码覆盖率,但是它给出了 NullPointerException

您只是为了代码覆盖率而这样做。这不是一个真正的好习惯,因为:

  1. 您正在膨胀代码库,以便为不属于您的代码职责的内容编写测试。
  2. 100% 的覆盖率并不意味着代码库没有错误。

现在,如果您的配置源dataSource 做了一些事情(除了检索它),您可能会为此编写一个测试来断言代码中的所有内容都正确使用它。但是,正如所写,它并没有任何帮助。

【讨论】:

  • 感谢您的建议,将仅进行简单测试。
  • 很高兴听到它有帮助。如果您的问题已经解决,请考虑接受答案。 :)
猜你喜欢
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
相关资源
最近更新 更多