Skip to content

Load files and mappings from src/test/resources by default #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ public class WireMockContainer extends GenericContainer<WireMockContainer> {
public static final DockerImageName WIREMOCK_2_LATEST =
DockerImageName.parse(OFFICIAL_IMAGE_NAME).withTag(WIREMOCK_2_LATEST_TAG);

private static final String MAPPINGS_DIR = "/home/wiremock/mappings/";
private static final String FILES_DIR = "/home/wiremock/__files/";
private static final String MAPPINGS_DIR = "mappings/";
private static final String FILES_DIR = "__files/";
private static final String CONTAINER_WORKING_DIR = "/home/wiremock/";
private static final String CONTAINER_MAPPINGS_DIR = CONTAINER_WORKING_DIR + MAPPINGS_DIR;
private static final String CONTAINER_FILES_DIR = CONTAINER_WORKING_DIR + FILES_DIR;

private static final String EXTENSIONS_DIR = "/var/wiremock/extensions/";
private static final int PORT = 8080;
Expand All @@ -81,6 +84,8 @@ public class WireMockContainer extends GenericContainer<WireMockContainer> {
private final Map<String, WireMockPlugin> plugins = new HashMap<>();
private boolean isBannerDisabled = true;

private File rootDir = new File("src/test/resources");

/**
* Create image from the specified full image name (repo, image, tag)
*/
Expand Down Expand Up @@ -130,7 +135,7 @@ public WireMockContainer withBanner() {
isBannerDisabled = false;
return this;
}

/**
* Adds CLI argument to the WireMock call.
* @param arg Argument
Expand Down Expand Up @@ -374,12 +379,15 @@ public Integer getPort() {
protected void configure() {
super.configure();
addExposedPorts(PORT);

loadAllFilesFromRootDirectory();

for (Stub stub : mappingStubs.values()) {
withCopyToContainer(Transferable.of(stub.json), MAPPINGS_DIR + stub.name + ".json");
withCopyToContainer(Transferable.of(stub.json), CONTAINER_MAPPINGS_DIR + stub.name + ".json");
}

for (Map.Entry<String, MountableFile> mount : mappingFiles.entrySet()) {
withCopyToContainer(mount.getValue(), FILES_DIR + mount.getKey());
withCopyToContainer(mount.getValue(), CONTAINER_FILES_DIR + mount.getKey());
}

final ArrayList<String> extensionClassNames = new ArrayList<>();
Expand All @@ -403,6 +411,54 @@ protected void configure() {
withCommand(wireMockArgs.toString());
}

/**
* Configures the root directory where mappings and files will be loaded recursively.
* If not set, {@code src/test/resources} will be used by default.
* <p>
* Files will be loaded from {@code $rootDir/__files} and mappings from {@code $rootDir/mappings}.
*
* @param rootDir the root directory
* @return this instance
*/
public WireMockContainer withRootDir(File rootDir) {
this.rootDir = rootDir;
return this;
}

private void loadAllFilesFromRootDirectory() {
if (rootDir == null || !rootDir.isDirectory()) {
return;
}

Path mappingsPath = rootDir.toPath().resolve(MAPPINGS_DIR);
getAllFiles(mappingsPath).forEach(path -> withMappingFromJSON(readAllContent(path)));

Path filesPath = rootDir.toPath().resolve(FILES_DIR);
getAllFiles(filesPath).forEach(path ->
withFile(filesPath.relativize(path).toString(), path.toFile()));
}

private List<Path> getAllFiles(Path path) {

if (!Files.exists(path)) {
return Collections.emptyList();
}

try (Stream<Path> stream = Files.walk(path)){
return stream.filter(Files::isRegularFile).collect(Collectors.toList());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private String readAllContent(Path path) {
try {
return new String(Files.readAllBytes(path));
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}

private static final class Stub {
final String name;
final String json;
Expand All @@ -412,6 +468,4 @@ public Stub(String name, String json) {
this.json = json;
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (C) 2025 WireMock Inc, Oleg Nenashev and all project contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wiremock.integrations.testcontainers;

import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.wiremock.integrations.testcontainers.testsupport.http.HttpResponse;
import org.wiremock.integrations.testcontainers.testsupport.http.TestHttpClient;

import java.io.File;

import static org.assertj.core.api.Assertions.assertThat;

@Testcontainers(parallel = true)
class WireMockContainerRootDirTest {
@Container
WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE)
.withMapping("hello", WireMockContainerRootDirTest.class, "hello.json")
.withFileFromResource("file.json", WireMockContainerRootDirTest.class, "file.json")
.withRootDir(new File("src/test/resources/root-dir"));

@Test
void testThatLoadsMappingFromRootDirectory() throws Exception {
// given
String url = wiremockServer.getUrl("hello/root/dir");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("response body")
.contains("Hello root dir");
}

@Test
void testThatLoadsMappingFromNestedRootDirectory() throws Exception {
// given
String url = wiremockServer.getUrl("hello/nested/root/dir");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("response body")
.contains("Hello nested root dir");
}

@Test
void testThatServesFileFromRootDirectory() throws Exception {
// given
String url = wiremockServer.getUrl("root-dir-file.json");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("response body")
.isEqualTo("{ \"message\": \"file from root dir\" }");
}

@Test
void testThatServesNestedFileFromRootDirectory() throws Exception {
// given
String url = wiremockServer.getUrl("nested/root-dir-nested-file.json");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("response body")
.isEqualTo("{ \"message\": \"nested file from root dir\" }");
}

@Test
void testThatDirectMappingsAndFilesAreLoadedWithCustomRootDirEnabled() throws Exception {
// given
String url = wiremockServer.getUrl("/hello");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("Wrong response body")
.contains("file contents from direct mapping");
}

@Test
void testThatDirectMappingsAndFilesAreLoadedEvenWhenRootDirIsSpecified() throws Exception {
// given
String url = wiremockServer.getUrl("/hello");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("Wrong response body")
.contains("file contents from direct mapping");
}

@Test
void testThatMappingsAndFileAreLoadedFromDefaultRootDir() throws Exception {

try (WireMockContainer wmc = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE)) {
wmc.start();

// given
String url = wmc.getUrl("/hello/default/root/dir");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("Wrong response body")
.contains("contents from default root dir file");
}
}

@Test
void testThatInvalidRootDirIsIgnored() throws Exception {

try (WireMockContainer wmc = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE)
.withMapping("hello", WireMockContainerRootDirTest.class, "hello.json")
.withFileFromResource("file.json", WireMockContainerRootDirTest.class, "file.json")
.withRootDir(new File("invalid/root/dir"))) {
wmc.start();

// given
String url = wmc.getUrl("/hello");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("Wrong response body")
.contains("file contents from direct mapping");
}
}

@Test
void testThatNullRootDirIsIgnored() throws Exception {

try (WireMockContainer wmc = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE)
.withMapping("hello", WireMockContainerRootDirTest.class, "hello.json")
.withFileFromResource("file.json", WireMockContainerRootDirTest.class, "file.json")
.withRootDir(null)) {
wmc.start();

// given
String url = wmc.getUrl("/hello");

// when
HttpResponse response = new TestHttpClient().get(url);

// then
assertThat(response.getBody())
.as("Wrong response body")
.contains("file contents from direct mapping");
}
}

}
1 change: 1 addition & 0 deletions src/test/resources/__files/default-root-dir-file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "message": "contents from default root dir file" }
10 changes: 10 additions & 0 deletions src/test/resources/mappings/hello-default-root-dir.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"request": {
"method": "GET",
"url": "/hello/default/root/dir"
},
"response": {
"status": 200,
"bodyFileName": "default-root-dir-file.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "message": "file contents from direct mapping" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"request": {
"method": "GET",
"url": "/hello"
},
"response": {
"status": 200,
"bodyFileName": "file.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "message": "nested file from root dir" }
1 change: 1 addition & 0 deletions src/test/resources/root-dir/__files/root-dir-file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "message": "file from root dir" }
10 changes: 10 additions & 0 deletions src/test/resources/root-dir/mappings/hello-root-dir.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"request": {
"method": "GET",
"url": "/hello/root/dir"
},
"response": {
"status": 200,
"body": "Hello root dir"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"request": {
"method": "GET",
"url": "/hello/nested/root/dir"
},
"response": {
"status": 200,
"body": "Hello nested root dir"
}
}