Skip to content

Commit

Permalink
Made it possibly to give a timeout value to receivedX methods when ve…
Browse files Browse the repository at this point in the history
…rifying requests. This fixes jadler-mocking#100
  • Loading branch information
Kreinoee committed Oct 26, 2017
1 parent 614089c commit 38e09d8
Show file tree
Hide file tree
Showing 9 changed files with 1,225 additions and 485 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package net.jadler;

import net.jadler.mocking.VerificationException;
import net.jadler.mocking.Verifying;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang.time.StopWatch;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;


import static net.jadler.Jadler.initJadler;
import static net.jadler.Jadler.closeJadler;
import static net.jadler.Jadler.port;
import static net.jadler.Jadler.verifyThatRequest;
import static net.jadler.Jadler.onRequest;



public class JadlerMockingAsyncIntegrationTest {

private StopWatch stopWatch;
private HttpClient client;
private ScheduledExecutorService exec;

@Before
public void init() {
initJadler();
this.stopWatch = new StopWatch();
this.client = new HttpClient();
this.exec = Executors.newSingleThreadScheduledExecutor();
}

@After
public void shutdown() {
closeJadler();
this.exec.shutdownNow();
}

@Test
public void callHasAlredyBeenMade() throws IOException {
stubOkOnExpectedRequest();
performExpectedRequest();
stopWatch.start();
verifyingObjForExpected()
.receivedOnce(Duration.ofSeconds(10));
stopWatch.stop();
assertThat(stopWatch.getTime(), lessThan(1000L));
// 1 seconds is just to make sure that the test does not fail, because it runs on
// very busy computer, it should actually just return without waiting at all.
}

@Test
public void callIsMadeAfterOneSecond() throws ExecutionException, InterruptedException {
stubOkOnExpectedRequest();
stopWatch.start();
final ScheduledFuture<Integer> performResult = this.exec.schedule(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return performExpectedRequest();
}
}, 1, TimeUnit.SECONDS);
verifyingObjForExpected().receivedOnce(Duration.ofSeconds(2));
stopWatch.stop();
assertEquals(200, performResult.get().intValue());
assertThat(stopWatch.getTime(), lessThan(2000L));
assertThat(stopWatch.getTime(), greaterThanOrEqualTo(1000L));
}

@Test
public void callIsNeverMadeShouldReturnTheExactSameExceptionAs() {
VerificationException expectedExeption = null;
try {
verifyingObjForExpected().receivedOnce();
fail("Should have catched an exception by now");
} catch (VerificationException e) {
expectedExeption = e;
}
Jadler.resetJadler();
stopWatch.start();
VerificationException result = null;
try {
verifyingObjForExpected().receivedOnce(Duration.ofMillis(200));
fail("Should have catched an exception by now");
} catch (VerificationException e) {
result = e;
}
stopWatch.stop();
assertThat(stopWatch.getTime(), greaterThanOrEqualTo(200L));
assertEquals(expectedExeption.getMessage(), result.getMessage());
}

private void stubOkOnExpectedRequest() {
addExpectedRequestToRequestMatching(onRequest())
.respond()
.withStatus(200);
}

private static Verifying verifyingObjForExpected() {
return addExpectedRequestToRequestMatching(verifyThatRequest());
}

private static <T extends RequestMatching<T>> T addExpectedRequestToRequestMatching(
final RequestMatching<T> r) {
return r
.havingMethodEqualTo("POST")
.havingPathEqualTo("/expectedPath")
.havingBodyEqualTo("expected body");
}

private int performExpectedRequest() throws IOException {
final PostMethod method = new PostMethod("http://localhost:"+port()+"/expectedPath");
method.setRequestEntity(new StringRequestEntity("expected body", "text/plain", "UTF-8"));
return client.executeMethod(method);
}
}
98 changes: 98 additions & 0 deletions jadler-core/src/main/java/net/jadler/Duration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package net.jadler;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import java.util.concurrent.TimeUnit;

/**
* Simple class to represent a Duration in some timeunit. It does this be
* holding the value as a long, and the type of timeunit as a TimeUnit enum value.
*
* When the library one day requires java8, this class should be removed, and replaced
* by java.time.Duration.
*
* This class is Immutable.
*/
public final class Duration {

private static class ZeroHolder {
public static final Duration instance = Duration.ofNanos(0L);
}

private final long value;
private final TimeUnit timeUnit;

public static Duration zero() {
return ZeroHolder.instance;
}

public static Duration ofNanos(final long value) {
return new Duration(value, TimeUnit.NANOSECONDS);
}

public static Duration ofMillis(final long value) {
return new Duration(value, TimeUnit.MILLISECONDS);
}

public static Duration ofSeconds(final long value) {
return new Duration(value, TimeUnit.SECONDS);
}

public static Duration ofMinutes(final long value) {
return new Duration(value, TimeUnit.MINUTES);
}

private Duration(final long value, final TimeUnit timeUnit) {
if (value < 0)
throw new IllegalArgumentException("Value of a Duratino cannot be negative");
this.value = value;
this.timeUnit = timeUnit;
}

public long getValue() {
return value;
}

public TimeUnit getTimeUnit() {
return timeUnit;
}

public long toNanos() {
return this.timeUnit.toNanos(this.value);
}

public boolean isZero() {
return this.value == 0;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;

if (!(o instanceof Duration)) return false;

Duration duration = (Duration) o;

return new EqualsBuilder()
.append(value, duration.value)
.append(timeUnit, duration.timeUnit)
.isEquals();
}

@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(value)
.append(timeUnit)
.toHashCode();
}

@Override
public String toString() {
return new ToStringBuilder(this)
.append("value", value)
.append("timeUnit", timeUnit)
.toString();
}
}
Loading

0 comments on commit 38e09d8

Please sign in to comment.