OkHttp MockWebServer fails to accept connections when restarted - java

I'm using the OkHttp MockWebServer to mock my server responses for unit tests.
It works great for the first test, but on the 2nd test my client fails with:
Failed to connect to localhost/0:0:0:0:0:0:0:1:63631
This happens even if the 2nd test is exactly the same as the 1st one.
Here's what I'm doing:
#RunWith(RobolectricTestRunner.class)
#Config(shadows = MyClassTest.MyNetworkSecurityPolicy.class,
manifest = "src/main/AndroidManifest.xml",
constants = BuildConfig.class,
sdk = 16)
public class MyClassTest {
private MockWebServer mockServer;
private MyServerApi serverApi;
#Before
public void setUp() throws Exception {
System.out.println("\ntest start");
this.mockServer = new MockWebServer();
this.mockServer.start();
this.serverApi = new MyServerApi(this.mockServer.url("/").toString());
}
#Test
public void testOne() throws Exception {
final String responseBody = // read response from file
this.mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(responseBody));
final Waiter waiter = new Waiter();
this.serverApi.getData("some_id", new Callback<MyResponseData> {
#Override
public void onResponse(final Call<MyResponseData> call, final Response<MyResponseData> response) {
waiter.assertEquals("some_value", response.body().getValue());
waiter.resume();
}
#Override
public void onFailure(final Call<T> call, final Throwable error) {
waiter.fail(error);
}
});
waiter.await();
final RecordedRequest recordedRequest = this.mockServer.takeRequest();
assertEquals("GET", recordedRequest.getMethod());
}
#Test
public void testTwo() throws Exception {
final String responseBody = // read response from file
this.mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(responseBody));
final Waiter waiter = new Waiter();
this.serverApi.getData("some_id", new Callback<MyResponseData> {
#Override
public void onResponse(final Call<MyResponseData> call, final Response<MyResponseData> response) {
waiter.assertEquals("some_value", response.body().getValue());
waiter.resume();
}
#Override
public void onFailure(final Call<T> call, final Throwable error) {
waiter.fail(error);
}
});
waiter.await();
final RecordedRequest recordedRequest = this.mockServer.takeRequest();
assertEquals("GET", recordedRequest.getMethod());
}
#After
public void tearDown() throws Exception {
System.out.println("test end\n");
this.mockServer.shutdown();
}
#Implements(NetworkSecurityPolicy.class)
public static class MyNetworkSecurityPolicy {
#Implementation
public static NetworkSecurityPolicy getInstance() {
try {
Class<?> shadow = MyNetworkSecurityPolicy.class.forName("android.security.NetworkSecurityPolicy");
return (NetworkSecurityPolicy) shadow.newInstance();
} catch (Exception e) {
throw new AssertionError();
}
}
#Implementation
public boolean isCleartextTrafficPermitted() {
return true;
}
}
}
The first test passes as it should, but the second one fails with the message I wrote above.
The output in the console is:
test start
okhttp3.mockwebserver.MockWebServer$3 execute
INFO: MockWebServer[63631] starting to accept connections
WARNING: no system properties value for gsm.sim.operator.alpha
okhttp3.mockwebserver.MockWebServer$4 processOneRequest
INFO: MockWebServer[63631] received request: GET REQUEST_PATH HTTP/1.1 and responded: HTTP/1.1 200 OK
okhttp3.mockwebserver.MockWebServer$3 acceptConnections
test end
INFO: MockWebServer[63631] done accepting connections: Socket closed
test start
okhttp3.mockwebserver.MockWebServer$3 execute
INFO: MockWebServer[63649] starting to accept connections
okhttp3.mockwebserver.MockWebServer$3 acceptConnections
INFO: MockWebServer[63649] done accepting connections: Socket closed
on error: Failed to connect to localhost/0:0:0:0:0:0:0:1:63631
test end
(The Waiter object thing is from the concurrentunit lib)
Any idea why this happens?

Your second request is using the URL of the first MockWebServer instance. (Each instance has a distinct URL.)

This localhost connection fails because it does not belong tot he mock server. Use this instead
(mockHelper.getHost()).willReturn(okhttpMockWebServer.url("/").toString())

Related

Mock ServerSocket in Spring Boot JUnit5

I'm trying to mock a socket connection and just verify if the order of the called methods is correct.
Here's my client:
#Component
public class Communicator extends Thread {
public void startTCPConnection() {
logger.debug("Trying to connect...");
try {
client = new Socket();
client.connect(new InetSocketAddress(ip, port), reconnectTimeout);
clientConnected = true;
startListener(); // FIRST METHOD TO VERIFY
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
login(); // SECOND METHOD TO VERIFY
} catch (Exception e) {
clientConnected = false;
isLoggedIn = false;
utility.sleep(reconnectTimeout);
startTCPConnection();
}
}
public void startListener() {
listener.start();
}
public void login() {
String loginSequence = "asdf";
send(loginSequence); // THIRD METHOD TO VERIFY
}
public void send(String message) {...}
// FOURTH METHOD TO VERIFY
public void handleMessageFromServer(String message) {
if (!isLoggedIn) {
handleLoginResult(message);
} else {
handleMessageAfterLogin(message);
}
}
// FIFTH METHOD TO VERIFY
public void handleLoginResult(String message) {
if (isLoginSuccessful(message)) {
isLoggedIn = true;
startHeartBeatSender();
}
}
public void startHeartBeatSender() {...}
}
And my unit test:
#Spy
private Communicator communicator;
#Test
public void testStartTCPConnection() throws IOException {
setupProperties();
communicator.start();
verify(communicator).startListener();
verify(communicator).login();
verify(communicator).send(correctLoginString);
verify(communicator).handleMessageFromServer(correctLoginResultString);
verify(communicator).handleLoginResult(correctLoginResultString);
verify(communicator).startHeartBeatSender();
So basically I want to have this order:
start thread (startTCPConnection)
startListener
login
send
handleMessageFromServer // receive OK from server
handleLoginResult // interpret the response from server as Login OK
startHeartBeatSender // start another thread
At the moment it dies at logger.debug("Trying to connect..."); I am getting a "Wanted but not invoked" exception.
The usual usage is having a third party server running and then just launching my own spring boot service that connects to the mentioned server.
Any help or direction is appreciated.
Your code is not designed for testing (at least not the stuff you want to test). new operator always is a sign that you can't test this invocation.
Try to redesign your code so it uses an injected Socket instead of creating it with new, so you can inject a mock there instead and your test does not rely on the .connect to acually work.
You also can try to inject a factory for Socket if direct injection doesn't work because you need the socket more than once per instance of your class. For the test you can then inject a mock factory that returns a mock Socket.

vert.x testing with TestNg

i am new to vert.x , i am trying to make unit testing by calling my webservices .
i need an example of testing webservices with testng.
when i did it with junit5 it works fine with the below code
#BeforeMethod
private static void deploy_verticle(Vertx vertx , VertxTestContext testContext) {
vertx.deployVerticle(new MainVerticle(), testContext.completing());
}
#Test
public void getTestFalse(Vertx vertx , VertxTestContext testContext) throws InterruptedException {
Assert.assertTrue("3".contains("tesdfsdf"));
req = new HttpRequestEntityTest();
req.setHost("localhost");
req.setPort(8089);
req.setUri("/api/data");
utilTest = new RestUtilTest();
response = new HttpResponseEntityTest();
utilTest.getTestUtil(req, testContext.succeeding(response -> {
testContext.verify(() -> {
Assert.assertTrue(response.getBodyStr().contains("tesdfsdf"));
});
testContext.completeNow();
}));
}
#AfterMethod
public void finish(Vertx vertx , VertxTestContext testContext) {
context.getVertx().close(context.getTestContext().succeeding(response -> {
context.getTestContext().completeNow();
}));
}
but when i try to work with TestNg like this :
#SuppressWarnings("deprecation")
#Test
public void getTestIqvia() throws InterruptedException {
Future<HttpResponseEntityTest> future = Future.future();
response = new HttpResponseEntityTest();
req = new HttpRequestEntityTest();
req.setHost("localhost");
req.setPort(8089);
req.setUri("/api/data");
utilTest = new RestUtilTest();
utilTest.getTestUtil(req, response -> {
System.out.println(response.result().getBodyStr());
System.out.println(response.result().getBodyStr().contains("dsds"));
Assert.assertTrue(response.result().getBodyStr().contains("fdsfds"));
});
GetTestUtil Function :
public Future<HttpResponseEntityTest> getTestUtil(HttpRequestEntityTest req,
Handler<AsyncResult<HttpResponseEntityTest>> resultHandler) {
future = Future.future();
WebClient client = WebClient.create(vertx);
response = new HttpResponseEntityTest();
client.get(req.getPort(), req.getHost(), req.getUri()).send(ar -> {
if (ar.succeeded()) {
response.setStatusCode(ar.result().statusCode());
response.setBodyStr(ar.result().bodyAsString());
future.complete(response);
System.out.println("Received response with status code get" + response.getStatusCode());
resultHandler.handle(Future.succeededFuture(response));
} else {
response.setErrorMsg(ar.cause().getMessage());
System.out.println("Something went wrong " + ar.cause().getMessage());
future.complete(response);
}
});
return future;
}
always sending to web client not entered in the arrow function ar and always test success because it doesn't go to Assert function . except fewtimes in debugging mode only
can any one has ana example in testNG with Vert.x?? or what's wrong in my code?
This happens because the getTestIqvia completes before the WebClient callback is invoked.
With jUnit5, the corresponding Vert.x test extension makes sure the test is not marked as passed until all the asynchronous assertions pass.
With TestNG you need to do this manually. In practice, you need to make the test wait until the future returned by getTestUtil is completed.

Unit testing Java Spark microframework

I am trying to add a restful api to a java microservice. For this, I am using spark:
http://sparkjava.com/documentation.html
I've created a very simple class which stands up an api. That class is here:
public class Routes {
public void establishRoutes(){
get("/test", (req, res) -> "Hello World");
after((req, res) -> {
res.type("application/json");
});
exception(IllegalArgumentException.class, (e, req, res) -> {
res.status(400);
});
}
Now, running Routes.establishRoutes() should stand up an api which would show "Hello World" in the event someone decides to visit http://localhost:4567/test. This does actually work. Hurray!
The next step is unit testing the code. My unit test, unfortunately, does not succeed. The spark documentation does not detail a sound way for doing testing so what I have is pieced together from examples I found around the net. Here is my Junit test:
public class TestRoutes {
#Before
public void setUp() throws Exception {
Routes newRoutes = new Routes();
newRoutes.establishRoutes();
}
#After
public void tearDown() throws Exception {
stop();
}
#Test
public void testModelObjectsPOST(){
String testUrl = "/test";
ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
Map<String, String> json = res.json();
assertEquals(201, res.status);
}
Here is the code behind ApiTestUtils.request():
public class ApiTestUtils {
public static TestResponse request(String method, String path, String requestBody) {
try {
URL url = new URL("http://localhost:4567" + path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(method);
connection.setDoOutput(true);
connection.connect();
String body = IOUtils.toString(connection.getInputStream());
return new TestResponse(connection.getResponseCode(), body);
} catch (IOException e) {
e.printStackTrace();
fail("Sending request failed: " + e.getMessage());
return null;
}
}
public static class TestResponse {
public final String body;
public final int status;
public TestResponse(int status, String body) {
this.status = status;
this.body = body;
}
public Map<String,String> json() {
return new Gson().fromJson(body, HashMap.class);
}
}
}
I am failing on connection.connect() inside ApiTestUtils.request(). Specifically, I get the error: java.lang.AssertionError: Sending request failed: Connection refused
I believe this is happening because the application isn't listening when my test tries to make the request. However, I don't understand why that would be the case. I borrowed the test code from the demo project found here:
https://github.com/mscharhag/blog-examples/blob/master/sparkdemo/src/test/java/com/mscharhag/sparkdemo/UserControllerIntegrationTest.java
UPDATE:
I tried running the example linked above. Turns out, it doesn't work either. Looks like spinning up a spark instance in this context is more difficult than I thought? I'm not trying to figure out how to do so.
In your test case is missing the code used for waiting the initialization of the embedded server.
I've tried your code and stumbled on the same issue as you did, but after debugging it I've noticed that the embedded spark server is initialized in a newly created thread. ( see the method spark.Service#init()).
All you need to do in your test is to await for the initialization by calling the method spark.Spark#awaitInitialization()
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.TestCase.assertEquals;
import static spark.Spark.awaitInitialization;
import static spark.Spark.stop;
public class TestRoutes {
#Before
public void setUp() throws Exception {
Routes newRoutes = new Routes();
newRoutes.establishRoutes();
awaitInitialization();
}
#After
public void tearDown() throws Exception {
stop();
}
#Test
public void testModelObjectsPOST() {
String testUrl = "/test";
ApiTestUtils.TestResponse res = ApiTestUtils.request("GET", testUrl, null);
assertEquals(200, res.status);
}
}
I can't help you with Spark, but if you're open to trying an alternative lightweight Java library for writing micro services, have a look at Molecule.
You'll find documentation and examples for writing unit tests and integration tests. If I understand what you're trying to test correctly, the test would look like:
HttpRequest request = new HttpRequest(4567);
HttpResponse response = request.get("/test");
assertThat(response).hasStatusCode(201)
.hasContentType("application/json")
.hasBodyText("Hello World");

How to know: How many requests is HttpServer-in-Vertx serving

I write a server with Vertx.
I have about 40k users. I can print every request but I don't know how to know how many current requests my server is serving
I used this class: http://vertx.io/docs/apidocs/io/vertx/core/http/HttpServer.html but this is no method to do it
Vertx is great toolkit but it can not show server status, really????
My server code:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
#Override
public void handle(HttpServerRequest request) {
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
}
});
httpServer.listen(9999);
}
}
Since vert.x 3.x.x http://vertx.io/docs/vertx-dropwizard-metrics is an official component of vert.x
I think what you search is this:
http://vertx.io/docs/vertx-dropwizard-metrics/java/#http-server-metrics
There are several possibilities to view the metrics
jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#jmx
http bridge for jmx http://vertx.io/docs/vertx-dropwizard-metrics/java/#_using_jolokia_and_hawtio
In our project we write periodically to a log file and send it in parallel to a graphite / grafana instance over udp
Vert.x requests are very short lived, so basing calculations solely on number of requests per second is not optimal. But, for the sake of discussion, you can achieve what you want in the following way:
public class MyFirstVerticle extends AbstractVerticle {
private HttpServer httpServer = null;
// Bad, done for the sake of simplicity
public final static AtomicInteger counter = new AtomicInteger(0);
#Override
public void start() throws Exception {
httpServer = vertx.createHttpServer();
httpServer.requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest request) {
counter.incrementAndGet();
String path = request.path();
System.out.println("incoming request: [" + request.remoteAddress() + "] at " + path);
request.response().end();
request.endHandler(new Handler<Void>() {
#Override
public void handle(Void aVoid) {
counter.decrementAndGet();
}
});
}
});
httpServer.listen(9999);
}
}
Then to test yourself you can try something like that:
public class Main {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
MyFirstVerticle verticle = new MyFirstVerticle();
vertx.deployVerticle(verticle);
// Very bad, but our request are very short
vertx.setPeriodic(1, new Handler<Long>() {
#Override
public void handle(Long aLong) {
// Otherwise will overflow our console
if (MyFirstVerticle.counter.intValue() > 0) {
System.out.println(MyFirstVerticle.counter.intValue());
}
}
});
}
}

How can I start the Google App Engine Java development server from JUnit?

I want to write automated tests that run against the local development web server. It's easy enough to write tests against the underlying services (https://cloud.google.com/appengine/docs/java/tools/localunittesting), but I'd like to test my full stack. I could start and kill the server using Runtime.exec(), but I'm hoping someone has developed a more elegant solution.
I found the answer in the Javadocs. Use DevAppServerTestRunner:
#RunWith(DevAppServerTestRunner.class)
#DevAppServerTest(EndToEndTest.TestConfig.class)
public class EndToEndTest {
private final LocalServiceTestHelper testHelper = new LocalServiceTestHelper(
new LocalURLFetchServiceTestConfig(), new LocalDatastoreServiceTestConfig());
public static class TestConfig extends BaseDevAppServerTestConfig {
public File getSdkRoot() {
return new File(...);
}
public File getAppDir() {
return new File(...);
}
public List<URL> getClasspath() {
return Arrays.asList(...);
}
}
#Before
public void setUpHelper() {
testHelper.setUp();
}
#After
public void tearDownHelper() {
testHelper.tearDown();
}
#Test
public void testEndToEnd() throws Exception {
URLFetchService fetchService = URLFetchServiceFactory.getURLFetchService();
HTTPResponse resp = fetchService.fetch(new URL("http://localhost:8080/insertFoo?id=33"));
Assert.assertEquals(200, resp.getResponseCode());
DatastoreServiceFactory.getDatastoreService().get(KeyFactory.createKey("foo", 33));
}
}

Categories

Resources