Spring 启动控制台应用程序导致 JUnit 测试用例等待

Spring Boot console application causes JUnit test case to wait

我有 Spring 接受用户输入的引导控制台应用程序。在同一个应用程序中,有执行某些逻辑的服务。

在 运行直接连接服务的 JUnit 测试用例时,我观察到控制台应用程序处于接受用户输入状态的行为,因此没有进入 JUnit 测试。

通常没有问题,因为对于正常的 Spring 引导应用程序,启动时 运行 没有任何问题。但是对于此控制台应用程序设置,它等待用户输入。

请问有什么方法可以让测试用例 运行 不触发控制台应用程序吗?非常感谢。

观察:控制台应用程序在 JUnit 测试用例上触发 运行,未输入测试用例

主要应用

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ToyRobotApplication implements CommandLineRunner {

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

    @Override
    public void run(String... args) throws Exception {
        // Instruct user to perform input
        System.out.println("Welcome to toy robot application!");
        System.out.println("Below are the possible operations:");
        System.out.println("PLACE <x-coordinate> <y-coordinate> <facing>");
        System.out.println("MOVE");
        System.out.println("LEFT");
        System.out.println("RIGHT");
        System.out.println("REPORT");

        while (true) {
            System.out.println("Please enter your command:");

            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String usrInput = br.readLine();
            //...

        }
    }
}

测试用例

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.somecompany.model.Facing;
import com.somecompany.model.Location;
import com.somecompany.model.Robot;
import com.somecompany.service.ToyRobotService;

@SpringBootTest
public class ToyRobotReportTest {

    @Autowired
    private Robot robot;

    @Autowired
    private ToyRobotService toyRobotService;

    @Test
    public void shouldBeAbleToReportLocation() {
        Location location = new Location();
        location.setXCor("1");
        location.setYCor("2");
        location.setFacing(Facing.NORTH);

        robot.setLocation(location);

        // Actual result
        String result = toyRobotService.report();

        // Assertion
        assertEquals("1,2,NORTH", result);
    }
}

注:省略其他来源

经过一番研究,我的设置工作正常。为了让它工作,JUnit 测试 class 不应使用通常的 @SpringBootTest 注释进行注释。

当 class 被注释为 @SpringBootTest 时,它将启动应用程序的上下文(即启动应用程序)。在大多数常见的测试场景中,如果没有等待用户输入,这应该没问题。

在我们的例子中,我们希望识别 Spring 引导注释(例如@Autowired),但不希望启动应用程序本身。

我们可以在 JUnit 中使用以下内容:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ToyRobotApplication.class, initializers = ConfigDataApplicationContextInitializer.class)
public class ToyRobotPlaceTest {
    ...
}

这将重新定义 spring 注释,但不会启动应用程序上下文。