0

I configured an Apache FtpServer as follows:

@Component
public class FtpDummyServer {

private FtpServer server;

@PostConstruct
public void init() throws FtpException {
    ..some initialization
    this.server = serverFactory.createServer();
    this.server.start();
}

@PreDestroy
public void stop() {
    this.server.stop();
}

Notice that the server is automatically started in the @PostConstruct. I have different tests configured in SpringBoot as follows:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MainApplication.class)
@WebIntegrationTest
public class ApplicationTestX {
...
}

When I run the tests individually, they succeed. However, when I run them together, I get a java.net.BindException: Address already in use: bind. How can I avoid that?

René Winkler
  • 6,508
  • 7
  • 42
  • 69

3 Answers3

5

If you take a look at exception stacktrace you will see what address ftp server tries to use. Smth like

Caused by: org.apache.ftpserver.FtpServerConfigurationException: Failed to bind to address 0.0.0.0/0.0.0.0:21, check configuration

It may happen because:

  1. Another instance of your app uses address. If so you need to terminate them.
  2. Some other process uses address/port. In this case you can reconfigure ftp server to bind to another address.

    FtpServerFactory serverFactory = new FtpServerFactory();
    
    ListenerFactory factory = new ListenerFactory();
    factory.setPort(2222); //use alternative port instead of default 21
    serverFactory.addListener("default", factory.createListener());
    
    server = serverFactory.createServer();
    server.start();
    

Use netstat to figure out process id that holds address.

Evgeny
  • 2,483
  • 1
  • 17
  • 24
2

For each test, an FtpDummyServer is created. However, @PreDestroy was never called. @DirtiesContext solves the problem.

René Winkler
  • 6,508
  • 7
  • 42
  • 69
0

Using @DirtiesContext with @TestExecutionListeners works but dont forget to merge your context with the default ones. E.g:

@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@TestExecutionListeners(value = {DirtiesContextTestExecutionListener.class}, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
@SpringApplicationConfiguration(classes = MainApplication.class)
@WebIntegrationTest
public class ApplicationTestX {
...
}

Have a look there: Does Spring @DirtiesContext reload Spring context?