springspring-bootjunit4spring-testspring-test-mvc

How to use random port for JUNIT Testcases using Spring Boot 1.4.0 +


I am using spring boot 1.3.6 and my JUNIT Test cases are running fine, after upgrading to spring boot 1.4.0 and attempting to remove deprecated classes is throwing me error

My JUNITCLASS with 1.3.x

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest({"server.port=0"})
public class CustomerControllerIT {

    @Value("${local.server.port}")
    private int port;
    private URL base;
    private RestTemplate template;

    @Autowired
    private DataBuilder dataBuilder;

    @Autowired
    private CustomerRepository customerRepository;

    private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8"; 


    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/rest/customers");
        template = new TestRestTemplate();      

        /* remove and reload test data */
        customerRepository.deleteAll();     
        dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));       
    }

    @Test
    public void getAllCustomers() throws Exception {
        ResponseEntity<String> response = template.getForEntity(base.toString(), String.class);     
        assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

        List<Customer> customers = convertJsonToCustomers(response.getBody());      
        assertThat(customers.size(), equalTo(3));       
    }

private List<Customer> convertJsonToCustomers(String json) throws Exception        {        
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, Customer.class));
}
}

MyClass with 1.4.0

Updates done

After Changes

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class , webEnvironment=WebEnvironment.RANDOM_PORT)
@WebAppConfiguration
public class CustomerControllerIT {

    @Value("${local.server.port}")
    private int port;
    private URL base;
    private TestRestTemplate template;

    @Autowired
    private DataBuilder dataBuilder;

    @Autowired
    private CustomerRepository customerRepository;

    private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8"; 


    @Before
    public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/rest/customers");
        template = new TestRestTemplate();      

        /* remove and reload test data */
        customerRepository.deleteAll();     
        dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));       
    }
}

Now I am receiving NPE when i try to run JUNIT Testcase, How can I set the random port to make my JUNIT test case running in Spring Boot 1.4.0 +?

Update :

Here is the stacktrace of the issue

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException
    at org.springframework.test.context.web.socket.MockServerContainerContextCustomizer.customizeContext(MockServerContainerContextCustomizer.java:38)
    at org.springframework.boot.test.context.SpringBootContextLoader$ContextCustomizerAdapter.initialize(SpringBootContextLoader.java:270)
    at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:633)
    at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:347)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 more

Solution

  • From Spring Blog I have updated your latest sample.

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = Application.class, webEnvironment=WebEnvironment.RANDOM_PORT)
    public class CustomerControllerIT {
        @Autowired
        private TestRestTemplate template;
    
        @Autowired
        private DataBuilder dataBuilder;
    
        @Autowired
        private CustomerRepository customerRepository;
    
        private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8"; 
    
    
        @Before
        public void setUp() throws Exception {
            /* remove and reload test data */
            customerRepository.deleteAll();     
            dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));       
        }
    
        @Test
        public void getAllCustomers() throws Exception {
            ResponseEntity<String> response = template.getForEntity("/rest/customers", String.class);     
            assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
    
            List<Customer> customers = convertJsonToCustomers(response.getBody());      
            assertThat(customers.size(), equalTo(3));       
        }
    }