如何对Spring @Bean CommandLineRunner进行单元测试?

时间:2015-04-10 10:17:25

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

我在一个小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'方法进行单元测试(使用protected或者使用powermock),但是我想知道是否有办法“完全”测试Spring @Bean。

3 个答案:

答案 0 :(得分: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实现会适当地调用其他服务。

答案 1 :(得分:0)

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

@Rule
public OutputCapture outputCapture = new OutputCapture();

在您的测试方法中:

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

答案 2 :(得分:0)

创建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中创建MyCommandLineRunnerTest。测试 .java

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

  @Autowired
  MyCommandLineRunner commandLineRunner;

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