Skip to content

Commit

Permalink
Merge pull request #541 from bitwiseman/wiremock-github-rule
Browse files Browse the repository at this point in the history
Add GitHubApiWireMockRule
  • Loading branch information
bitwiseman committed Sep 11, 2019
2 parents 44a70b3 + 8dee552 commit c796d18
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 91 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.15</version>
<version>1.18</version>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java15</artifactId>
<artifactId>java17</artifactId>
<version>1.0</version>
</signature>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public abstract class AbstractGitHubApiTestBase extends AbstractGitHubApiWireMoc

@Before
public void setUp() throws Exception {
assumeTrue( "All tests inheriting from this class are not guaranteed to work without proxy", useProxy);
assumeTrue( "All tests inheriting from this class are not guaranteed to work without proxy", githubApi.isUseProxy());
}

protected GHUser getUser() {
Expand Down
96 changes: 33 additions & 63 deletions src/test/java/org/kohsuke/github/AbstractGitHubApiWireMockTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
import org.kohsuke.github.junit.GitHubApiWireMockRule;
import org.kohsuke.github.junit.WireMockRule;

import java.io.File;
Expand All @@ -21,55 +23,36 @@
import static com.github.tomakehurst.wiremock.client.WireMock.*;

/**
* @author Kohsuke Kawaguchi
* @author Liam Newman
*/
public abstract class AbstractGitHubApiWireMockTest extends Assert {

// By default the wiremock tests will run without proxy or taking a snapshot.
// The tests will use only the stubbed data and will fail if requests are made for missing data.
// You can use the proxy without taking a snapshot while writing and debugging tests.
// You cannot take a snapshot without proxying.
protected final static boolean takeSnapshot = System.getProperty("test.github.takeSnapshot", "false") != "false";
protected final static boolean useProxy = takeSnapshot || System.getProperty("test.github.useProxy", "false") != "false";
private final GitHubBuilder githubBuilder = createGitHubBuilder();

public final static String STUBBED_USER_LOGIN = "placeholder-user";
public final static String STUBBED_USER_PASSWORD = "placeholder-password";

/**
* {@link GitHub} instance for use during test.
* Traffic will be part of snapshot when taken.
*/
protected GitHub gitHub;
private final String baseFilesClassPath = this.getClass().getName().replace('.', '/');
protected final String baseRecordPath = "src/test/resources/" + baseFilesClassPath + "/wiremock";

/**
* {@link GitHub} instance for use before/after test.
* Traffic will not be part of snapshot when taken.
* Should only be used when isUseProxy() or isTakeSnapShot().
*/
protected GitHub gitHubBeforeAfter;

protected final String baseFilesClassPath = this.getClass().getName().replace('.', '/');
protected final String baseRecordPath = "src/test/resources/" + baseFilesClassPath + "/wiremock";

@Rule
public WireMockRule githubApi = new WireMockRule(WireMockConfiguration.options()
.dynamicPort()
.usingFilesUnderDirectory(baseRecordPath)
.extensions(
new ResponseTransformer() {
@Override
public Response transform(Request request, Response response, FileSource files,
Parameters parameters) {
if ("application/json"
.equals(response.getHeaders().getContentTypeHeader().mimeTypePart())
&& !response.getHeaders().getHeader("Content-Encoding").containsValue("gzip")) {
return Response.Builder.like(response)
.but()
.body(response.getBodyAsString()
.replace("https://api.github.com/",
"http://localhost:" + githubApi.port() + "/")
)
.build();
}
return response;
}

@Override
public String getName() {
return "github-api-url-rewrite";
}
})
public GitHubApiWireMockRule githubApi = new GitHubApiWireMockRule(
WireMockConfiguration.options()
.dynamicPort()
.usingFilesUnderDirectory(baseRecordPath)
);

private static GitHubBuilder createGitHubBuilder() {
Expand All @@ -96,13 +79,6 @@ private static GitHubBuilder createGitHubBuilder() {
} catch (IOException e) {
}

if (!useProxy) {
// This sets the user and password to a placeholder for wiremock testing
// This makes the tests believe they are running with permissions
// The recorded stubs will behave like they running with permissions
builder.withPassword(STUBBED_USER_LOGIN, STUBBED_USER_PASSWORD);
}

return builder.withRateLimitHandler(RateLimitHandler.FAIL);
}

Expand All @@ -112,31 +88,25 @@ protected GitHubBuilder getGitHubBuilder() {

@Before
public void wireMockSetup() throws Exception {
if(useProxy) {
githubApi.stubFor(
proxyAllTo("https://api.github.com/")
.atPriority(100)
);
} else {
// Just to be super clear
githubApi.stubFor(
any(urlPathMatching(".*"))
.willReturn(status(500).withBody("Stubbed data not found. Set test.github.use-proxy to have WireMock proxy to github"))
.atPriority(100));
}
GitHubBuilder builder = getGitHubBuilder();

if (!githubApi.isUseProxy()) {
// This sets the user and password to a placeholder for wiremock testing
// This makes the tests believe they are running with permissions
// The recorded stubs will behave like they running with permissions
builder.withPassword(STUBBED_USER_LOGIN, STUBBED_USER_PASSWORD);
}

gitHub = getGitHubBuilder()
gitHub = builder
.withEndpoint("http://localhost:" + githubApi.port())
.build();
}

@After
public void snapshotRequests() {
if (takeSnapshot) {
githubApi.snapshotRecord(recordSpec()
.forTarget("https://api.github.com")
.extractTextBodiesOver(255));
if (githubApi.isUseProxy()) {
gitHubBeforeAfter = builder
.withEndpoint("https://api.github.com/")
.build();
} else {
gitHubBeforeAfter = null;
}
}
}
10 changes: 5 additions & 5 deletions src/test/java/org/kohsuke/github/GHOrganizationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class GHOrganizationTest extends AbstractGitHubApiTestBase {
@Override
public void setUp() throws Exception {
super.setUp();
if (useProxy) {
if (githubApi.isUseProxy()) {
org = gitHub.getOrganization("github-api-test-org");
}
}
Expand All @@ -39,9 +39,9 @@ public void testCreateRepositoryWithAutoInitialization() throws IOException {

@After
public void cleanUp() throws Exception {
if (useProxy) {
GHRepository repository = org.getRepository(GITHUB_API_TEST);
repository.delete();
}
if (githubApi.isUseProxy()) {
GHRepository repository = org.getRepository(GITHUB_API_TEST);
repository.delete();
}
}
}
23 changes: 14 additions & 9 deletions src/test/java/org/kohsuke/github/PullRequestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
*/
public class PullRequestTest extends AbstractGitHubApiWireMockTest {

@Before
@After
public void cleanUp() throws Exception {
// Cleanup is only needed when proxying
if (!githubApi.isUseProxy()) return;

for (GHPullRequest pr : getRepository(this.gitHubBeforeAfter).getPullRequests(GHIssueState.OPEN)) {
pr.close();
}
}

@Test
public void createPullRequest() throws Exception {
String name = "createPullRequest";
Expand Down Expand Up @@ -220,17 +231,11 @@ public void getUser() throws IOException {
}
}

@After
public void cleanUp() throws Exception {
// Cleanup is only needed when proxying
if (useProxy) {
for (GHPullRequest pr : getRepository().getPullRequests(GHIssueState.OPEN)) {
pr.close();
}
}
protected GHRepository getRepository() throws IOException {
return getRepository(gitHub);
}

private GHRepository getRepository() throws IOException {
private GHRepository getRepository(GitHub gitHub) throws IOException {
return gitHub.getOrganization("github-api-test-org").getRepository("github-api");
}
}
22 changes: 11 additions & 11 deletions src/test/java/org/kohsuke/github/WireMockStatusReporterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public class WireMockStatusReporterTest extends AbstractGitHubApiWireMockTest {

@Test
public void user_whenProxying_AuthCorrectlyConfigured() throws Exception {
assumeFalse("Test only valid when not taking a snapshot", takeSnapshot);
assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable)", useProxy);
assumeFalse("Test only valid when not taking a snapshot", githubApi.isTakeSnapshot());
assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable)", githubApi.isUseProxy());

assertThat(
"GitHub connection believes it is anonymous. Make sure you set GITHUB_OAUTH or both GITHUB_USER and GITHUB_PASSWORD environment variables",
Expand All @@ -42,8 +42,8 @@ public void user_whenProxying_AuthCorrectlyConfigured() throws Exception {

@Test
public void user_whenNotProxying_Stubbed() throws Exception {
assumeFalse("Test only valid when not taking a snapshot", takeSnapshot);
assumeFalse("Test only valid when not proxying", useProxy);
assumeFalse("Test only valid when not taking a snapshot", githubApi.isTakeSnapshot());
assumeFalse("Test only valid when not proxying", githubApi.isUseProxy());

assertThat(gitHub.isAnonymous(), is(false));
assertThat(gitHub.login, equalTo(STUBBED_USER_LOGIN));
Expand All @@ -59,8 +59,8 @@ public void user_whenNotProxying_Stubbed() throws Exception {

@Test
public void BasicBehaviors_whenNotProxying() throws Exception {
assumeFalse("Test only valid when not taking a snapshot", takeSnapshot);
assumeFalse("Test only valid when not proxying", useProxy);
assumeFalse("Test only valid when not taking a snapshot", githubApi.isTakeSnapshot());
assumeFalse("Test only valid when not proxying", githubApi.isUseProxy());

Exception e = null;
GHRepository repo = null;
Expand Down Expand Up @@ -96,8 +96,8 @@ public void BasicBehaviors_whenNotProxying() throws Exception {

@Test
public void BasicBehaviors_whenProxying() throws Exception {
assumeFalse("Test only valid when not taking a snapshot", takeSnapshot);
assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable)", useProxy);
assumeFalse("Test only valid when not taking a snapshot", githubApi.isTakeSnapshot());
assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable)", githubApi.isUseProxy());
Exception e = null;
GHRepository repo = null;

Expand All @@ -123,15 +123,15 @@ public void BasicBehaviors_whenProxying() throws Exception {

@Test
public void whenSnapshot_EnsureProxy() throws Exception {
assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", takeSnapshot);
assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", githubApi.isTakeSnapshot());

assertTrue("When taking a snapshot, proxy should automatically be enabled", useProxy);
assertTrue("When taking a snapshot, proxy should automatically be enabled", githubApi.isUseProxy());
}

@Ignore("Not implemented yet")
@Test
public void whenSnapshot_EnsureRecordToExpectedLocation() throws Exception {
assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", takeSnapshot);
assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", githubApi.isTakeSnapshot());

}
}
94 changes: 94 additions & 0 deletions src/test/java/org/kohsuke/github/junit/GitHubApiWireMockRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.kohsuke.github.junit;

import com.github.tomakehurst.wiremock.common.FileSource;
import com.github.tomakehurst.wiremock.core.Options;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.extension.Parameters;
import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
import com.github.tomakehurst.wiremock.http.Request;
import com.github.tomakehurst.wiremock.http.Response;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.status;

/**
* @author Liam Newman
*/
public class GitHubApiWireMockRule extends WireMockRule {

// By default the wiremock tests will run without proxy or taking a snapshot.
// The tests will use only the stubbed data and will fail if requests are made for missing data.
// You can use the proxy without taking a snapshot while writing and debugging tests.
// You cannot take a snapshot without proxying.
private final static boolean takeSnapshot = System.getProperty("test.github.takeSnapshot", "false") != "false";
private final static boolean useProxy = takeSnapshot || System.getProperty("test.github.useProxy", "false") != "false";

public GitHubApiWireMockRule(WireMockConfiguration options) {
this(options, true);
}

public GitHubApiWireMockRule(WireMockConfiguration options, boolean failOnUnmatchedRequests) {
super(options
.extensions(
new ResponseTransformer() {
@Override
public Response transform(Request request, Response response, FileSource files,
Parameters parameters) {
if ("application/json"
.equals(response.getHeaders().getContentTypeHeader().mimeTypePart())
&& !response.getHeaders().getHeader("Content-Encoding").containsValue("gzip")) {
return Response.Builder.like(response)
.but()
.body(response.getBodyAsString()
.replace("https://api.github.com/",
"http://localhost:" + request.getPort() + "/")
)
.build();
}
return response;
}

@Override
public String getName() {
return "github-api-url-rewrite";
}
}),
failOnUnmatchedRequests);
}

public boolean isUseProxy() {
return GitHubApiWireMockRule.useProxy;
}

public boolean isTakeSnapshot() {
return GitHubApiWireMockRule.takeSnapshot;
}

@Override
protected void before() {
super.before();
if(isUseProxy()) {
this.stubFor(
proxyAllTo("https://api.github.com/")
.atPriority(100)
);
} else {
// Just to be super clear
this.stubFor(
any(urlPathMatching(".*"))
.willReturn(status(500).withBody("Stubbed data not found. Set test.github.use-proxy to have WireMock proxy to github"))
.atPriority(100));
}
}

@Override
protected void after() {
super.after();
if (isTakeSnapshot()) {
this.snapshotRecord(recordSpec()
.forTarget("https://api.github.com")
.captureHeader("If-None-Match")
.extractTextBodiesOver(255));
}
}
}
Loading

0 comments on commit c796d18

Please sign in to comment.