4

I have a JUnit test class written in spring boot which contains 3 unit tests:

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

If run after the first test, i am getting below the exception:

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

though the application context released, it is not releasing the port number, hence i'm getting the above exception.

Is there any way that I can close the port number before each unit test?

Bhanuchandar Challa
  • 1,123
  • 2
  • 9
  • 17

3 Answers3

2

You should consider starting your Spring Boot application by using the SpringApplication class rather than invoking directly the main(String[] args) method of your Spring Boot application that doesn't provide an API to terminate it.

With the SpringApplication way, you could get a ConfigurableApplicationContext instance that provides a way to terminate the running application.

For example :

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

However, you should be cautious about this way of doing.
Starting the Spring Boot application is a relatively expensive operation.
Executing it for any method of test will make slower the tests execution.
Unit tests should be fast.
Integration tests that are executing on a integration machine may be slower.
You should also consider this problematic.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • SpringApplicationBuilder previous version (1.1.4) doesn't contain build method to build the application and start. So, I have changed the code to: Solution 1: context = new SpringApplicationBuilder(Application.class).web(false).run(); Solution 2: SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class); app.sources(Application.class); app.web(false); context = app.run(); but in both the cases, application is not starting up. – Bhanuchandar Challa Jun 20 '17 at 09:38
  • You may need to use {@BeforeEach} and {@AfterEach} as per this reply: https://stackoverflow.com/a/51515680/1617124 – Lars Nov 26 '19 at 20:38
  • @Lars That is possible. My answer relies on JUnit4 while the other on JUnit5. – davidxxx Feb 09 '20 at 07:30
1

Use @After and @Before to handle before and after calls for each unit test.

tsolakp
  • 5,858
  • 1
  • 22
  • 28
1

You could be running into the issue because of more than one springboot tests and you may be using something like surefire to executes test classes in parallel.

With Spring boot you can randomize the port in each junit class as defined below. But note this will be at class level and not at test level.

But I don't really see a need at method level. Springboot tests are slow, so I would advise against it.

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

Shibashis
  • 8,023
  • 3
  • 27
  • 38