如何在Spring启动应用程序中的每个JUnit测试后释放端口号?

时间:2017-06-19 16:40:09

标签: java unit-testing spring-boot junit

我有一个用Spring Boot编写的JUnit测试类,它包含3个单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@ContextConfiguration
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class AppclaitionTest {

    @BeforeClass
    public static void initialize(){
        System.out.println(">>>>>>>Intialization Part!");
    }

    @Test
    public void test1(){
        System.out.println(">>>>>>>Appcliation Test Started! - Test 1");
        Application.main(new String[]{});
        System.out.println(">>>>>>>Appcliation Test Ended! - Test 1");
    }

    @Test
    public void test2(){
        System.out.println(">>>>>>>Appcliation Test Started! - Test 2");
        Application.main(new String[]{});
        System.out.println(">>>>>>>Appcliation Test Ended! - Test 2");
    }

    @Test
    public void test3(){
        System.out.println(">>>>>>>Appcliation Test Started! - Test 3");
        Application.main(new String[]{});
        System.out.println(">>>>>>>Appcliation Test Ended! - Test 3");
    }

    @AfterClass
    public static void destory(){
        System.out.println(">>>>>>>Destroy Part!");
    }
}

如果在第一次测试后运行,我将低于例外:

java.net.BindException: Address already in use: bind

虽然发布了应用程序上下文,但它没有发布端口号,因此我得到了上述异常。

在每次单元测试之前,我有什么办法可以关闭端口号吗?

3 个答案:

答案 0 :(得分:2)

由于有多个springboot测试,您可能会遇到问题,并且您可能正在使用类似surefire的内容来并行执行测试类。

使用Spring引导,您可以随机化每个junit类中的端口,如下所述。但请注意,这将是在班级而不是测试级别。

但我并没有真正看到方法层面的需求。 Springboot测试很慢,所以我建议反对它。

@SpringBootTest(classes = Application.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

答案 1 :(得分:1)

使用@After@Before来处理每个单元测试的来电之前和之后。

答案 2 :(得分:1)

您应该考虑使用SpringApplication类启动Spring Boot应用程序,而不是直接调用Spring Boot应用程序的main(String[] args)方法,该方法不提供API来终止它。

使用SpringApplication方式,您可以获得一个ConfigurableApplicationContext实例,该实例提供了终止正在运行的应用程序的方法。

例如:

ConfigurableApplicationContext context;

@Before
public void setup{
    SpringApplication springApplication = new SpringApplicationBuilder()           
            .sources(Application.class)
            .build();
    context = springApplication.run();
}

@After
public void tearDown(){
    SpringApplication.exit(context);
}

@Test
 public void test1(){         
    // action
       ...
    // assertion
       ...
 }

但是,你应该对这种做法持谨慎态度 启动Spring Boot应用程序是一项相对昂贵的操作 对任何测试方法执行它都会使测试执行变慢。
单元测试应该很快。
在集成机器上执行的集成测试可能会更慢 你也应该考虑这个问题。