ribbon-eureka: start Eureka and SimpleApplication programmatically
nyg opened this issue · 1 comments
concerns ribbon-eureka
Hello,
To run the HelloClientApplicationTest test successfully I need to manually start EurekaServerApplication and SimpleApplication. HelloClientApplication will be started before the test by the @SpringApplicationConfiguration annotation.
My question is, how can I avoid manually starting both EurekaServerApplication and SimpleApplication? I've tried two things:
// HelloClientApplicationTests.java
public void clientConnects() throws Exception {
new Thread(
() -> new SpringApplicationBuilder(EurekaServerApplication.class)
.properties("spring.config.name:eureka", "logging.level.com.netflix.discovery:OFF")
.run()).start();
new Thread(
() -> new SpringApplicationBuilder(SimpleApplication.class)
.properties("spring.config.name:simple")
.run()).start();
ResponseEntity<String> response = new TestRestTemplate().getForEntity("http://localhost:" + port, String.class);
assertNotNull("response was null", response);
assertEquals("Wrong status code", HttpStatus.OK, response.getStatusCode());
assertEquals("Hello", response.getBody());
}
and
public void clientConnects() throws Exception {
exec(EurekaServerApplication.class);
Thread.sleep(20 * 1000);
exec(SimpleApplication.class);
Thread.sleep(20 * 1000);
ResponseEntity<String> response = new TestRestTemplate().getForEntity("http://localhost:" + port, String.class);
assertNotNull("response was null", response);
assertEquals("Wrong status code", HttpStatus.OK, response.getStatusCode());
assertEquals("Hello", response.getBody());
}
// http://stackoverflow.com/questions/636367/executing-a-java-application-in-a-separate-process
public static void exec(Class klass) throws IOException, InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getCanonicalName();
new ProcessBuilder(javaBin, "-cp", classpath, className).start();
}
What's interesting with the last piece of code (not sure how portable it is) is that after the test has failed, the two created process are still running and can be reached. For some reason I can't reach them while the test is running (even with a breakpoint). And neither can HelloClientApplication...
The reason I want to do this is for the tests to be run by some continuous integration software (we use Bamboo).
Thanks a lot,
nyg
Ok, I manage to get it working, the trick was to use redirectError()
and redirectOutput()
on the process builder... However, I'd still like your input on how good (or not) my solution is :).
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = HelloClientApplication.class)
@WebIntegrationTest(randomPort = true)
public class HelloClientApplicationTests {
@Autowired
EurekaDiscoveryClient discoveryClient;
@Value("${local.server.port}")
int port;
@Test
public void clientConnects() throws Exception {
Process eureka = exec(EurekaServerApplication.class, "eureka_logs.txt");
Process simple = exec(SimpleApplication.class, "simple_logs.txt");
while (!discoveryClient.getServices().containsAll(Arrays.asList("helloclient", "simple"))) {
Thread.sleep(500);
}
ResponseEntity<String> response = new TestRestTemplate().getForEntity("http://localhost:" + port, String.class);
assertNotNull("Response was null!", response);
assertEquals("Wrong status code!", HttpStatus.OK, response.getStatusCode());
assertEquals("Hello", response.getBody());
eureka.destroyForcibly();
simple.destroyForcibly();
}
// http://stackoverflow.com/questions/636367/executing-a-java-application-in-a-separate-process
private Process exec(Class<?> klass, String fileName) throws IOException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
String classPath = System.getProperty("java.class.path");
String className = klass.getCanonicalName();
File processOutput = new File(fileName);
return new ProcessBuilder(javaBin, "-cp", classPath, className).redirectOutput(processOutput).redirectError(processOutput).start();
}
}