简体   繁体   中英

How to unit test an Spring @Bean CommandLineRunner?

I'm using Spring Boot in a little PoC, and I'm trying to test a @Bean implementation. I have this code:

@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...
    }
...
}

How can I unit test this @Bean commandLineRunner? Yeah, maybe I could unit test the 'fillDBData' method (putting protected or with powermock), but I would like to learn if there's a way to test the Spring @Bean "completely".

Here's how you could test with an integration test.

@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...
    }

}

That being said, my preference would be to create a named service that implements command line runner and then unit test it with all of its dependencies mocked out. In my opinion, it's not critical to test that Spring is going to call the CommandLineRunner bean when the application loads, but that the CommandLineRunner implementation calls other services appropriately.

You can use OutputCapture to see what you print in the console

@Rule
public OutputCapture outputCapture = new OutputCapture();

in your test method:

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

Create MyApplication class

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

Create MyCommandLineRunner class

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.");
  }
}

Create MyConfiguration class (you may not need @EntityScan and @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 {

}

Create MyCommandLineRunnerTest in src. test .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");
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM