【问题标题】:How to unit test an Spring @Bean CommandLineRunner?如何对 Spring @Bean CommandLineRunner 进行单元测试?
【发布时间】:2015-06-16 00:33:48
【问题描述】:

我在一个小 PoC 中使用 Spring Boot,并且我正在尝试测试一个 @Bean 实现。我有这个代码:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    CommandLineRunner init(@Value("${db.resetAndLoadOnStartup:true}") boolean resetAndLoadOnStartup,
                           SequenceIdRepository sequenceRepository,
                           UserAccountRepository userAccountRepository,
                           BookRepository bookRepository) {
        return args -> {
            log.info("Init Application...");
            if (resetAndLoadOnStartup) {
                fillDBData(sequenceRepository, userAccountRepository, bookRepository);
            }
            log.info("Aplication initiated!");
        };
    }

    private void fillDBData(SequenceIdRepository sequenceRepository,
                            UserAccountRepository userAccountRepository,
                            BookRepository bookRepository) {
        // Some code...
    }
...
}

如何对这个@Bean commandLineRunner 进行单元测试?是的,也许我可以对“fillDBData”方法进行单元测试(设置受保护或使用 powermock),但我想了解是否有办法“完全”测试 Spring @Bean。

【问题讨论】:

  • 我认为您将不得不在这里进行集成测试。
  • 是的,我猜到了,但我不知道如何在测试中“调用”bean:S

标签: java spring unit-testing spring-boot spring-test


【解决方案1】:

您可以使用OutputCapture 来查看您在控制台中打印的内容

@Rule
public OutputCapture outputCapture = new OutputCapture();

在你的测试方法中:

String output = this.outputCapture.toString();
    assertTrue(output, output.contains("Aplication initiated!"));

【讨论】:

  • 我说的不是测试日志... :) 我说的是测试@Bean
【解决方案2】:

以下是使用集成测试进行测试的方法。

@RunWith(SpringJUnit4ClassRunner.class)
// Or create a test version of Application.class that stubs out services used by the CommandLineRunner
@SpringApplicationConfiguration(classes = Application.class)
public class CommandLineRunnerIntegrationTest {

    @Autowired
    private CommandLineRunner clr;

    @Test
    public void thatCommandLineRunnerDoesStuff() throws Exception {
        this.clr.run();
        // verify changes...
    }

}

话虽如此,我的偏好是创建一个实现命令行运行器的命名服务,然后对它进行单元测试,并模拟掉它的所有依赖项。在我看来,测试 Spring 是否会在应用程序加载时调用 CommandLineRunner bean 并不重要,但 CommandLineRunner 实现是否适当地调用了其他服务。

【讨论】:

  • 谢谢,我试试。是的,我更喜欢模拟其余的依赖项。
【解决方案3】:

创建 MyApplication 类

package com.company.project;
//imports
@SpringBootApplication(scanBasePackages = "com.company.project")
public class FileToDbApplication {
  public static void main(String[] args) {
    SpringApplication.run(FileToDbApplication.class, args);
  }
}

创建 MyCommandLineRunner 类

package com.company.project;
//imports
@Component
public class MyCommandLineRunner implements CommandLineRunner {
  @Autowired
  private SurValueService surValueService;

  @Override
  public void run(String... args) {
    System.out.println("App started with " + args.length + " parameters.");
  }
}

创建 MyConfiguration 类(您可能不需要 @EntityScan@EnableJpaRepositories

package com.company.project;
//imports
@SpringBootConfiguration
@ComponentScan("com.company.project")
@EnableAutoConfiguration
@EntityScan(basePackages = "com.company.project.model")
@EnableJpaRepositories(basePackages = "com.company.project.service")
public class MyConfiguration {

}

在 src.test.java 中创建 MyCommandLineRunnerTest

package com.company.project;
//imports
@ExtendWith(SpringExtension.class)
@SpringBootTest
class MyCommandLineRunnerTest {

  @Autowired
  MyCommandLineRunner commandLineRunner;

  @Test
  public void testMain() {
    commandLineRunner.run("input.txt", "input2.txt");
  }
}

【讨论】:

    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 2019-10-27
    • 2014-04-27
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多