Skip to content

Commit

Permalink
Merge pull request #54 from andrzejchm/develop
Browse files Browse the repository at this point in the history
release 0.2.1
  • Loading branch information
andrzejchm authored Feb 28, 2017
2 parents 47be866 + b5ac6e0 commit 19c0f61
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 12 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Add the dependency

```groovy
dependencies {
androidTestCompile 'com.github.andrzejchm.RESTMock:android:0.2.0'
androidTestCompile 'com.github.andrzejchm.RESTMock:android:0.2.1'
}
```

Expand Down Expand Up @@ -165,7 +165,7 @@ RESTMockServer.whenGET(pathEndsWith(path))
.thenReturnString("3rd call")
.delay(TimeUnit.SECONDS, 20, 30, 40)
```
this will result in `1st call` being returned after 5 seconds, `2nd call` being returned after 10 seconds, `3rd call` being returned after 15 seconds, another one after 20 seconds, and another after 30 seconds, and then every consecutive response with 40 seconds delay
this will result in `1st call` being delayed by 5 seconds, `2nd call` delayed by 10 seconds, `3rd call` delayed by 15 seconds, another one by 20 seconds, and another by 30 seconds, and then every consecutive response with 40 seconds delay

##Request verification
It is possible to verify which requests were called and how many times thanks to `RequestsVerifier`. All you have to do is call one of these:
Expand All @@ -184,6 +184,19 @@ RequestsVerifier.verifyGET(pathEndsWith("users")).invoked();
RequestsVerifier.verifyGET(pathEndsWith("users")).never();
```

Additionaly, you can manualy inspect requests received by RESTMockServer. All you have to do is to obtain them trough:

```java
//gets 5 most recent requests received. (ordered from oldest to newest)
RequestsVerifier.takeLast(5);

//gets 5 oldest requests received. (ordered from oldest to newest)
RequestsVerifier.takeFirst(5);

//gets all GET requests. (ordered from oldest to newest)
RequestsVerifier.takeAllMatching(isGET());
```

##Logging
RESTMock supports logging events. You just have to provide the RESTMock with the implementation of `RESTMockLogger`. For Android there is an `AndroidLogger` implemented already. All you have to do is use the `RESTMockTestRunner` or call

Expand Down
3 changes: 1 addition & 2 deletions androidsample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ dependencies {
exclude module: 'recyclerview-v7'
}
testCompile "org.robolectric:robolectric:3.2.2"



testCompile project(':android')
testCompile 'org.khronos:opengl-api:gl1.1-android-2.1_r1' //required to resolve robolectric test problems
testCompile(project(':core')) {
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ allprojects {
jcenter()
maven { url "https://jitpack.io" }
}
version = "0.2.0"
version = "0.2.1"
}

ext.preDexLibraries = project.hasProperty('preDexLibraries')
Expand Down
2 changes: 1 addition & 1 deletion core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ apply plugin: 'java'
apply plugin: 'maven'
apply from: '../quality_tools/findbugs.gradle'


sourceCompatibility = 1.7
targetCompatibility = 1.7

Expand Down Expand Up @@ -47,6 +46,7 @@ dependencies {
testCompile 'junit:junit:4.11'
testCompile 'org.mockito:mockito-all:1.9.5'
testCompile "com.squareup.okhttp3:okhttp:${okHttpVersion}"
testCompile 'com.google.code.findbugs:annotations:2.0.3'
}

jar.dependsOn test
Expand Down
68 changes: 68 additions & 0 deletions core/src/main/java/io/appflate/restmock/RequestsVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import org.hamcrest.Matcher;
import org.hamcrest.core.AllOf;

import java.util.LinkedList;
import java.util.List;

import io.appflate.restmock.exceptions.RequestInvocationCountMismatchException;
import io.appflate.restmock.exceptions.RequestInvocationCountNotEnoughException;
import io.appflate.restmock.exceptions.RequestNotInvokedException;
Expand Down Expand Up @@ -138,6 +141,71 @@ public static RequestVerification verifyPUT(Matcher<RecordedRequest> matcher) {
return verifyRequest(AllOf.allOf(RequestMatchers.isPUT(), matcher));
}

/**
* @param count number of most recent requests to return from the history of requests received by RESTMockServer.
* @return List of {@code count}-newest requests received by RESTMockServer (from oldest to newest).
*/
public static List<RecordedRequest> takeLast(int count) {
List<RecordedRequest> requestHistory = dispatcher.getRequestHistory();
return requestHistory.subList(Math.max(0, requestHistory.size() - count), requestHistory.size());
}

/**
* @return Most recent request received by RESTMockServer, or null if there were no recorded requests
*/
public static RecordedRequest takeLast() {
List<RecordedRequest> lastRequest = takeLast(1);
if (lastRequest.isEmpty()) {
return null;
} else {
return lastRequest.get(0);
}
}

/**
* @param count number of requests to return from the beginning of the history of requests received by RESTMockServer.
* @return List of {@code count}-oldest requests received by RESTMockServer (from oldest to newest).
*/
public static List<RecordedRequest> takeFirst(int count) {
List<RecordedRequest> requestHistory = dispatcher.getRequestHistory();
return requestHistory.subList(0, Math.min(count, requestHistory.size()));
}

/**
* @return Oldest recorded request received by RESTMockServer, or null if there were no recorded requests
*/
public static RecordedRequest takeFirst() {
List<RecordedRequest> lastRequest = takeFirst(1);
if (lastRequest.isEmpty()) {
return null;
} else {
return lastRequest.get(0);
}
}

/**
* @param fromIndexInclusive low endpoint (inclusive) of the sublist of requests' history.
* @param toIndexExclusive high endpoint (exclusive) of the sublist of requests' history.
* @return specified range of requests' history (from oldest to newest).
*/
public static List<RecordedRequest> take(int fromIndexInclusive, int toIndexExclusive) {
return dispatcher.getRequestHistory().subList(fromIndexInclusive, toIndexExclusive);
}

/**
* @param requestMatcher matcher used to find all relevant requests
* @return a list of requests received by RESTMockServer, that match the given {@code requestMatcher} (from oldest to newest).
*/
public static List<RecordedRequest> takeAllMatching(Matcher<RecordedRequest> requestMatcher) {
List<RecordedRequest> result = new LinkedList<>();
for (RecordedRequest recordedRequest : dispatcher.getRequestHistory()) {
if (requestMatcher.matches(recordedRequest)) {
result.add(recordedRequest);
}
}
return result;
}

private RequestsVerifier() {
throw new UnsupportedOperationException();
}
Expand Down
146 changes: 146 additions & 0 deletions core/src/test/java/io/appflate/restmock/RequestVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
import org.junit.Test;

import java.io.IOException;
import java.util.List;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.appflate.restmock.exceptions.RequestInvocationCountMismatchException;
import io.appflate.restmock.exceptions.RequestInvocationCountNotEnoughException;
import io.appflate.restmock.exceptions.RequestNotInvokedException;
import io.appflate.restmock.utils.RequestMatchers;
import io.appflate.restmock.utils.TestUtils;
import okhttp3.mockwebserver.RecordedRequest;

Expand All @@ -36,6 +39,8 @@
import static io.appflate.restmock.RequestsVerifier.verifyPUT;
import static io.appflate.restmock.RequestsVerifier.verifyRequest;
import static io.appflate.restmock.utils.RequestMatchers.pathEndsWith;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;

Expand Down Expand Up @@ -105,6 +110,147 @@ public void testHTTPMethodVerifier() throws Exception {
verifyDELETE(INVOKED_MATCHER).exactly(4);
}

@Test
public void takesLastNumOfElementsWhenHistoryNotEmpty() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

List<RecordedRequest> recordedRequests = RequestsVerifier.takeLast(3);
assertEquals(3, recordedRequests.size());
assertEquals("POST", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("DELETE", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("HEAD", recordedRequests.get(2).getMethod().toUpperCase());
}

@Test
public void takeLastNumOfElementsExceedsHistorySizeTakesWholeHistory() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

List<RecordedRequest> recordedRequests = RequestsVerifier.takeLast(10);
assertEquals(4, recordedRequests.size());
assertEquals("GET", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("POST", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("DELETE", recordedRequests.get(2).getMethod().toUpperCase());
assertEquals("HEAD", recordedRequests.get(3).getMethod().toUpperCase());
}

@Test(expected = IllegalArgumentException.class)
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
public void takeLastNumOfElementsWithInvalidCountThrowsException() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

RequestsVerifier.takeLast(-10);
}

@Test
public void takesFirstNumOfElementsWhenHistoryNotEmpty() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

List<RecordedRequest> recordedRequests = RequestsVerifier.takeFirst(3);
assertEquals(3, recordedRequests.size());
assertEquals("GET", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("POST", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("DELETE", recordedRequests.get(2).getMethod().toUpperCase());
}

@Test
public void takeFirstNumOfElementsExceedsHistorySizeTakesAllHistory() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

List<RecordedRequest> recordedRequests = RequestsVerifier.takeFirst(10);
assertEquals(4, recordedRequests.size());
assertEquals("GET", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("POST", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("DELETE", recordedRequests.get(2).getMethod().toUpperCase());
assertEquals("HEAD", recordedRequests.get(3).getMethod().toUpperCase());
}

@Test
public void takesSubsetOfRequests() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

List<RecordedRequest> recordedRequests = RequestsVerifier.take(1, 4);
assertEquals(3, recordedRequests.size());
assertEquals("POST", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("DELETE", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("HEAD", recordedRequests.get(2).getMethod().toUpperCase());
}

@Test(expected = IllegalArgumentException.class)
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
public void takesSubsetOfRequestsWithInvalidRangeThrowsError() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

RequestsVerifier.take(5, 3);
}

@Test
public void takeMatchingFindsAllRelevantRequests() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.get(path);
TestUtils.head(path);
TestUtils.get(path);
List<RecordedRequest> recordedRequests = RequestsVerifier.takeAllMatching(RequestMatchers.isGET());
assertEquals(3, recordedRequests.size());
assertEquals("GET", recordedRequests.get(0).getMethod().toUpperCase());
assertEquals("GET", recordedRequests.get(1).getMethod().toUpperCase());
assertEquals("GET", recordedRequests.get(2).getMethod().toUpperCase());
}

@Test(expected = IllegalArgumentException.class)
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
public void takeFirstNumOfElementsWithInvalidCountThrowsException() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
TestUtils.get(path);
TestUtils.post(path);
TestUtils.delete(path);
TestUtils.head(path);

RequestsVerifier.takeFirst(-10);
}

@Test
public void takeSingleFirstWhenNoHistoryIsNull() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
assertNull(RequestsVerifier.takeFirst());
}

@Test
public void takeSingleLastWhenNoHistoryIsNull() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
assertNull(RequestsVerifier.takeLast());
}

@Test
public void testReset() throws Exception {
RESTMockServer.whenRequested(pathEndsWith(path)).thenReturnString("a single call");
Expand Down
14 changes: 9 additions & 5 deletions core/src/test/java/io/appflate/restmock/utils/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,27 @@ public class TestUtils {

public static Response get(String path) throws IOException {
path = normalizePath(path);
return executeSync(new Request.Builder().url(RESTMockServer.getUrl() + path).build());
return executeSync(requestBuilder().url(RESTMockServer.getUrl() + path).build());
}

public static Response post(String path) throws IOException {
path = normalizePath(path);
return executeSync(new Request.Builder().url(RESTMockServer.getUrl() + path).method("POST", EMPTY_JSON_BODY).build());
return executeSync(requestBuilder().url(RESTMockServer.getUrl() + path).method("POST", EMPTY_JSON_BODY).build());
}

public static Response put(String path) throws IOException {
path = normalizePath(path);
return executeSync(new Request.Builder().url(RESTMockServer.getUrl() + path).method("PUT", EMPTY_JSON_BODY).build());
return executeSync(requestBuilder().url(RESTMockServer.getUrl() + path).method("PUT", EMPTY_JSON_BODY).build());
}

public static Response delete(String path) throws IOException {
path = normalizePath(path);
return executeSync(new Request.Builder().url(RESTMockServer.getUrl() + path).method("DELETE", null).build());
return executeSync(requestBuilder().url(RESTMockServer.getUrl() + path).method("DELETE", null).build());
}

public static Response head(String path) throws IOException {
path = normalizePath(path);
return executeSync(new Request.Builder().url(RESTMockServer.getUrl() + path).method("HEAD", null).build());
return executeSync(requestBuilder().url(RESTMockServer.getUrl() + path).method("HEAD", null).build());
}

private static Response executeSync(Request request) throws IOException {
Expand Down Expand Up @@ -93,4 +93,8 @@ private static String normalizePath(String path) {
}
return path;
}

private static Request.Builder requestBuilder() {
return new Request.Builder().addHeader("Connection", "close");
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

supportLibraryVersion=25.1.1
supportLibraryVersion=25.2.0
okHttpVersion=3.4.1
org.gradle.configureondemand=true

0 comments on commit 19c0f61

Please sign in to comment.