Skip to content

Commit b113ff3

Browse files
authored
Merge pull request hub4j#537 from bitwiseman/wiremock
Add WireMock testing facility
2 parents 0f7ae3c + e46a9f3 commit b113ff3

36 files changed

Lines changed: 2394 additions & 12 deletions

.github/workflows/maven.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ jobs:
1616
- name: Maven Download all dependencies
1717
run: mvn -B org.apache.maven.plugins:maven-dependency-plugin:3.1.1:go-offline
1818
- name: Maven Build
19-
run: mvn -B package --file pom.xml -DskipTests
19+
run: mvn -B package --file pom.xml -Dtest=GistTest,UserTest

pom.xml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<spotbugs-maven-plugin.version>3.1.11</spotbugs-maven-plugin.version>
3333
<spotbugs.version>3.1.12</spotbugs.version>
3434
<spotbugs-maven-plugin.failOnError>true</spotbugs-maven-plugin.failOnError>
35+
<hamcrest.version>2.1</hamcrest.version>
3536
</properties>
3637

3738
<build>
@@ -127,18 +128,31 @@
127128
<artifactId>commons-codec</artifactId>
128129
<version>1.7</version>
129130
</dependency>
131+
<dependency>
132+
<groupId>org.hamcrest</groupId>
133+
<artifactId>hamcrest</artifactId>
134+
<version>${hamcrest.version}</version>
135+
<scope>test</scope>
136+
</dependency>
137+
<!-- This is needed in order to force junit4 and JTH tests to use newer hamcrest version -->
138+
<dependency>
139+
<groupId>org.hamcrest</groupId>
140+
<artifactId>hamcrest-core</artifactId>
141+
<version>${hamcrest.version}</version>
142+
<scope>test</scope>
143+
</dependency>
144+
<dependency>
145+
<groupId>org.hamcrest</groupId>
146+
<artifactId>hamcrest-library</artifactId>
147+
<version>${hamcrest.version}</version>
148+
<scope>test</scope>
149+
</dependency>
130150
<dependency>
131151
<groupId>junit</groupId>
132152
<artifactId>junit</artifactId>
133153
<version>4.12</version>
134154
<scope>test</scope>
135155
</dependency>
136-
<dependency>
137-
<groupId>org.hamcrest</groupId>
138-
<artifactId>hamcrest-all</artifactId>
139-
<version>1.3</version>
140-
<scope>test</scope>
141-
</dependency>
142156
<dependency>
143157
<groupId>com.fasterxml.jackson.core</groupId>
144158
<artifactId>jackson-databind</artifactId>
@@ -197,6 +211,12 @@
197211
<version>${spotbugs.version}</version>
198212
<optional>true</optional>
199213
</dependency>
214+
<dependency>
215+
<groupId>com.github.tomakehurst</groupId>
216+
<artifactId>wiremock-jre8-standalone</artifactId>
217+
<version>2.24.1</version>
218+
<scope>test</scope>
219+
</dependency>
200220
</dependencies>
201221
<repositories>
202222
<repository>

src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public abstract class AbstractGitHubApiTestBase extends Assert {
1818

1919
protected GitHub gitHub;
2020

21+
2122
@Before
2223
public void setUp() throws Exception {
2324
File f = new File(System.getProperty("user.home"), ".github.kohsuke2");
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package org.kohsuke.github;
2+
3+
import com.github.tomakehurst.wiremock.common.FileSource;
4+
import com.github.tomakehurst.wiremock.common.SingleRootFileSource;
5+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
6+
import com.github.tomakehurst.wiremock.extension.Parameters;
7+
import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
8+
import com.github.tomakehurst.wiremock.http.Request;
9+
import com.github.tomakehurst.wiremock.http.Response;
10+
import com.github.tomakehurst.wiremock.junit.WireMockRule;
11+
import org.junit.Assert;
12+
import org.junit.Before;
13+
import org.junit.Rule;
14+
15+
import java.io.File;
16+
17+
import static com.github.tomakehurst.wiremock.client.WireMock.*;
18+
19+
/**
20+
* @author Kohsuke Kawaguchi
21+
*/
22+
public abstract class AbstractGitHubApiWireMockTest extends Assert {
23+
24+
protected GitHub gitHub;
25+
protected final String baseFilesClassPath = this.getClass().getName().replace('.', '/');;
26+
protected final String baseRecordPath = "src/test/resources/" + baseFilesClassPath;
27+
28+
public static WireMockRuleFactory factory = new WireMockRuleFactory();
29+
30+
@Rule
31+
public WireMockRule githubApi = factory.getRule(WireMockConfiguration.options()
32+
.dynamicPort()
33+
.usingFilesUnderClasspath(baseFilesClassPath + "/api")
34+
.extensions(
35+
new ResponseTransformer() {
36+
@Override
37+
public Response transform(Request request, Response response, FileSource files,
38+
Parameters parameters) {
39+
try {
40+
if ("application/json"
41+
.equals(response.getHeaders().getContentTypeHeader().mimeTypePart())) {
42+
// Something strange happending here... turning off for now
43+
// return Response.Builder.like(response)
44+
// .but()
45+
// .body(response.getBodyAsString()
46+
// .replace("https://api.github.com/",
47+
// "http://localhost:" + githubApi.port() + "/")
48+
// .replace("https://raw.githubusercontent.com/",
49+
// "http://localhost:" + githubRaw.port() + "/")
50+
// )
51+
// .build();
52+
}
53+
} catch (Exception e) {
54+
}
55+
return response;
56+
}
57+
58+
@Override
59+
public String getName() {
60+
return "url-rewrite";
61+
}
62+
63+
})
64+
);
65+
66+
@Before
67+
public void prepareMockGitHub() throws Exception {
68+
new File(baseRecordPath + "/api/mappings").mkdirs();
69+
new File(baseRecordPath + "/api/__files").mkdirs();
70+
71+
githubApi.stubFor(proxyAllTo("https://api.github.com/").atPriority(10));
72+
73+
githubApi.enableRecordMappings(new SingleRootFileSource(baseRecordPath + "/api/mappings"),
74+
new SingleRootFileSource(baseRecordPath + "/api/__files"));
75+
76+
gitHub = GitHubBuilder.fromEnvironment()
77+
.withEndpoint("http://localhost:" + githubApi.port())
78+
.withRateLimitHandler(RateLimitHandler.FAIL)
79+
.build();
80+
81+
}
82+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.kohsuke.github;
2+
3+
import com.github.tomakehurst.wiremock.common.FileSource;
4+
import com.github.tomakehurst.wiremock.common.SingleRootFileSource;
5+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
6+
import com.github.tomakehurst.wiremock.extension.Parameters;
7+
import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
8+
import com.github.tomakehurst.wiremock.http.Request;
9+
import com.github.tomakehurst.wiremock.http.Response;
10+
import com.github.tomakehurst.wiremock.junit.WireMockRule;
11+
import org.junit.Assert;
12+
import org.junit.Before;
13+
import org.junit.Rule;
14+
15+
import java.io.File;
16+
17+
import static com.github.tomakehurst.wiremock.client.WireMock.proxyAllTo;
18+
19+
/**
20+
* @author Kohsuke Kawaguchi
21+
*/
22+
public abstract class AbstractGitHubApiWithRawWireMockTest extends AbstractGitHubApiWireMockTest {
23+
24+
@Rule
25+
public WireMockRule githubRaw = factory.getRule(WireMockConfiguration.options()
26+
.dynamicPort()
27+
.usingFilesUnderClasspath(baseFilesClassPath + "/raw")
28+
);
29+
30+
@Before
31+
public void prepareMockRawGitHub() throws Exception {
32+
new File(baseRecordPath + "/raw/mappings").mkdirs();
33+
new File(baseRecordPath + "/raw/__files").mkdirs();
34+
35+
githubRaw.stubFor(proxyAllTo("https://raw.githubusercontent.com/").atPriority(10));
36+
37+
githubRaw.enableRecordMappings(new SingleRootFileSource(baseRecordPath + "/raw/mappings"),
38+
new SingleRootFileSource(baseRecordPath + "/raw/__files"));
39+
}
40+
}

src/test/java/org/kohsuke/github/GistTest.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package org.kohsuke.github;
22

3+
import com.github.tomakehurst.wiremock.stubbing.Scenario;
34
import org.junit.Test;
45

6+
import static com.github.tomakehurst.wiremock.client.WireMock.*;
7+
import static org.hamcrest.Matchers.notNullValue;
8+
9+
import static org.hamcrest.core.Is.is;
10+
511
/**
612
* @author Kohsuke Kawaguchi
713
*/
8-
public class GistTest extends AbstractGitHubApiTestBase {
14+
public class GistTest extends AbstractGitHubApiWireMockTest {
915
/**
1016
* CRUD operation.
1117
*/
@@ -18,9 +24,9 @@ public void lifecycleTest() throws Exception {
1824
.file("def.txt","def")
1925
.create();
2026

21-
assertNotNull(gist.getCreatedAt());
22-
assertNotNull(gist.getUpdatedAt());
27+
assertThat(gist.getCreatedAt(), is(notNullValue()));
2328

29+
assertNotNull(gist.getUpdatedAt());
2430
assertNotNull(gist.getCommentsUrl());
2531
assertNotNull(gist.getCommitsUrl());
2632
assertNotNull(gist.getGitPullUrl());
@@ -35,8 +41,10 @@ public void starTest() throws Exception {
3541
GHGist gist = gitHub.getGist("9903708");
3642
assertEquals("rtyler",gist.getOwner().getLogin());
3743

44+
3845
gist.star();
3946
assertTrue(gist.isStarred());
47+
4048
gist.unstar();
4149
assertFalse(gist.isStarred());
4250

@@ -65,7 +73,7 @@ public void gistFile() throws Exception {
6573
assertEquals(1,gist.getFiles().size());
6674
GHGistFile f = gist.getFile("keybase.md");
6775

68-
assertEquals("text/plain", f.getType());
76+
assertEquals("text/markdown", f.getType());
6977
assertEquals("Markdown", f.getLanguage());
7078
assertTrue(f.getContent().contains("### Keybase proof"));
7179
assertNotNull(f.getContent());

src/test/java/org/kohsuke/github/UserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/**
1010
* @author Kohsuke Kawaguchi
1111
*/
12-
public class UserTest extends AbstractGitHubApiTestBase {
12+
public class UserTest extends AbstractGitHubApiWireMockTest {
1313
@Test
1414
public void listFollowsAndFollowers() throws IOException {
1515
GHUser u = gitHub.getUser("rtyler");
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2016 CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*
24+
*/
25+
26+
package org.kohsuke.github;
27+
28+
import com.github.tomakehurst.wiremock.common.SingleRootFileSource;
29+
import com.github.tomakehurst.wiremock.core.Options;
30+
import com.github.tomakehurst.wiremock.junit.WireMockRule;
31+
32+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
33+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
34+
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
35+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
36+
37+
public class WireMockRuleFactory {
38+
private String urlToMock = System.getProperty("wiremock.record");
39+
40+
public WireMockRule getRule(int port) {
41+
return getRule(wireMockConfig().port(port));
42+
}
43+
44+
public WireMockRule getRule(Options options) {
45+
if (urlToMock != null && !urlToMock.isEmpty()) {
46+
return new WireMockRecorderRule(options, urlToMock);
47+
} else {
48+
return new WireMockRule(options);
49+
}
50+
}
51+
52+
private class WireMockRecorderRule extends WireMockRule {
53+
//needed for WireMockRule file location
54+
private String mappingLocation = "src/test/resources";
55+
56+
public WireMockRecorderRule(Options options, String url) {
57+
super(options);
58+
this.stubFor(get(urlMatching(".*")).atPriority(10).willReturn(aResponse().proxiedFrom(url)));
59+
this.enableRecordMappings(new SingleRootFileSource(mappingLocation + "/mappings"),
60+
new SingleRootFileSource(mappingLocation + "/__files"));
61+
}
62+
}
63+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"url": "https://api.github.com/gists/bf0058f87bb7c773123bb1763a6bb9b3",
3+
"forks_url": "https://api.github.com/gists/bf0058f87bb7c773123bb1763a6bb9b3/forks",
4+
"commits_url": "https://api.github.com/gists/bf0058f87bb7c773123bb1763a6bb9b3/commits",
5+
"id": "bf0058f87bb7c773123bb1763a6bb9b3",
6+
"node_id": "MDQ6R2lzdGJmMDA1OGY4N2JiN2M3NzMxMjNiYjE3NjNhNmJiOWIz",
7+
"git_pull_url": "https://gist.github.com/bf0058f87bb7c773123bb1763a6bb9b3.git",
8+
"git_push_url": "https://gist.github.com/bf0058f87bb7c773123bb1763a6bb9b3.git",
9+
"html_url": "https://gist.github.com/bf0058f87bb7c773123bb1763a6bb9b3",
10+
"files": {
11+
"keybase.md": {
12+
"filename": "keybase.md",
13+
"type": "text/markdown",
14+
"language": "Markdown",
15+
"raw_url": "https://gist.githubusercontent.com/bitwiseman/bf0058f87bb7c773123bb1763a6bb9b3/raw/2b68396d836af8c5b6ba905f27c4baf94ceb0ed3/keybase.md",
16+
"size": 2131
17+
}
18+
},
19+
"public": true,
20+
"created_at": "2019-08-31T07:01:58Z",
21+
"updated_at": "2019-08-31T07:01:58Z",
22+
"description": "",
23+
"comments": 0,
24+
"user": null,
25+
"comments_url": "https://api.github.com/gists/bf0058f87bb7c773123bb1763a6bb9b3/comments",
26+
"owner": {
27+
"login": "bitwiseman",
28+
"id": 1958953,
29+
"node_id": "MDQ6VXNlcjE5NTg5NTM=",
30+
"avatar_url": "https://avatars3.githubusercontent.com/u/1958953?v=4",
31+
"gravatar_id": "",
32+
"url": "https://api.github.com/users/bitwiseman",
33+
"html_url": "https://github.com/bitwiseman",
34+
"followers_url": "https://api.github.com/users/bitwiseman/followers",
35+
"following_url": "https://api.github.com/users/bitwiseman/following{/other_user}",
36+
"gists_url": "https://api.github.com/users/bitwiseman/gists{/gist_id}",
37+
"starred_url": "https://api.github.com/users/bitwiseman/starred{/owner}{/repo}",
38+
"subscriptions_url": "https://api.github.com/users/bitwiseman/subscriptions",
39+
"organizations_url": "https://api.github.com/users/bitwiseman/orgs",
40+
"repos_url": "https://api.github.com/users/bitwiseman/repos",
41+
"events_url": "https://api.github.com/users/bitwiseman/events{/privacy}",
42+
"received_events_url": "https://api.github.com/users/bitwiseman/received_events",
43+
"type": "User",
44+
"site_admin": false
45+
},
46+
"truncated": false
47+
}

0 commit comments

Comments
 (0)