Code Monkey home page Code Monkey logo

wiremock-spring-boot's Introduction

WireMock Spring Boot

WireMock Spring Boot library drastically simplifies WireMock configuration in a Spring Boot and JUnit 5 application.

๐Ÿคฉ Highlights

  • fully declarative WireMock setup
  • support for multiple WireMockServer instances - one per HTTP client as recommended in the WireMock documentation
  • automatically sets Spring environment properties
  • does not pollute Spring application context with extra beans

๐Ÿค” How to install

Add the dependency to wiremock-spring-boot:

<dependency>
    <groupId>com.maciejwalkowiak.spring</groupId>
    <artifactId>wiremock-spring-boot</artifactId>
    <version>2.1.2</version>
    <scope>test</scope>
</dependency>

โœจ How to use

Use @EnableWireMock with @ConfigureWireMock with tests annotated that use SpringExtension, like @SpringBootTest:

@SpringBootTest
@EnableWireMock({
        @ConfigureWireMock(name = "user-service", property = "user-client.url")
})
class TodoControllerTests {

    @InjectWireMock("user-service")
    private WireMockServer wiremock;

    @Value("${user-client.url}")
    private String wiremockUrl; // injects the base URL of the WireMockServer instance

    @Test
    void aTest() {
        wiremock.stubFor(...);
    }
}
  • @EnableWireMock adds test context customizer and enables WireMockSpringExtension
  • @ConfigureWireMock creates a WireMockServer and passes the WireMockServer#baseUrl to a Spring environment property with a name given by property.
  • @InjectWireMock injects WireMockServer instance to a test

Note that WireMockServer instances are not added as beans to Spring application context to avoid polluting it with test-related infrastructure. Instead, instances are kept in a separate store associated with an application context.

Registering WireMock extensions

WireMock extensions can be registered independently with each @ConfigureWireMock:

@ConfigureWireMock(name = "...", property = "...", extensions = { ... })

Customizing mappings directory

By default, each WireMockServer is configured to load mapping files from a classpath directory wiremock/{server-name}/mappings.

It can be changed with setting stubLocation on @ConfigureWireMock:

@ConfigureWireMock(name = "...", property = "...", stubLocation = "my-stubs")

Sounds good? Consider โค๏ธ Sponsoring the project! Thank you!

๐Ÿ™ Credits

I looked into and learned few concepts from following projects and resources during the development of this project:

wiremock-spring-boot's People

Contributors

maciejwalkowiak avatar scordio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wiremock-spring-boot's Issues

Injecting Wiremock does not work with JUnit @Nested

When trying to use a global WiremockServer in a test inside a nested test class annotated with @nested, the test cannot invoke any stubs because the WiremockServer is null.
I get the below running in a nested class, but without the nesting then the tests run fine and the wiremock works as expected.

java.lang.NullPointerException: Cannot invoke "com.github.tomakehurst.wiremock.WireMockServer.stubFor(com.github.tomakehurst.wiremock.client.MappingBuilder)" because "this.this$0.graphWiremock" is null

Provide wiremock.server.port property

The property wiremock.server.port is provided by spring-cloud-contract. To ease migration from that to this library, it would be nice if this library provided that property.

Add support for injections the other way around

Hi, thanks for this project as it looks like it can make handling WireMock within Spring Boot tests much easier!

We have a somewhat different use-case: we use JUnit5 to write and run "blackbox integration-style" tests. We need to use a static well-defined port for WireMock but we allow overriding it via Spring Property. We'd like to be able to use an existing SpringBoot Property to configure the WireMock Port.

We looked into using a WireMockConfigurationCustomizer to set the port, but this doesn't get the Spring Context passed into it as far as we could tell.

As a side note: The system under test runs in a different JVM, so our Spring Context only contains Test utilities. As such, it would not be a problem (it would even be preferable) for us to actually have WireMock be a first-class @Bean citizen within the Spring Context used by our tests. This way we could inject configuration properties into it like any other bean.

Spring 3.2.0 Incompatibility

Basically this: wiremock/wiremock#2395

As far as I understood Spring 3.2.0 uses jetty 12 instead of 11 (which is used by wiremock), creating an incompatibility that manifests itself as:

java.lang.NoClassDefFoundError: jakarta/servlet/DispatcherType

This is solveable by replacing the wiremock dependency with wiremock-standalone:

     <dependency>
            <groupId>com.maciejwalkowiak.spring</groupId>
            <artifactId>wiremock-spring-boot</artifactId>
            <version>2.0.0</version>
            <scope>test</scope>
            <exclusions>                
                <exclusion>
                    <groupId>org.wiremock</groupId>
                    <artifactId>wiremock</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.wiremock</groupId>
            <artifactId>wiremock-standalone</artifactId>
            <version>3.3.1</version>
            <scope>test</scope>
        </dependency>

However, I don't know which drawbacks this brings with itself.

To be fair, this is definetly a wiremock problem. I just wanted to leave my solution here in case anyone else comes across this error.
And maybe to track the issue in the context of this repository.

Configure WireMock with port

I had to add this code, would be nice if this was added to the tool.

  private @Value("${wiremock.server.url}") String wireMockUrl;

  @PostConstruct
  public void basePostConstruct() throws MalformedURLException {
    WireMock.configureFor(new URL(wireMockUrl).getPort());
  }

Allow injecting port without host/protocol (e.g., for gRPC)

I appreciate how easy this project makes it to configure WireMock for Spring Boot tests, but there's one thing that unfortunately prevented me from adopting it: We have some gRPC services that I would like to mock, with WireMocks gRPC support, but they can't be configured to use an HTTP url. Instead, I'd like to be able to do something like this:

@EnableWireMock({
        @ConfigureWireMock(name = "user-service", portProperty = "user-grpc-client.port", extensions = { new GrpcExtensionFactory() })
})

And then in application-test.yaml, do something like this:

user-grpc-client:
  target: "localhost:${user-grpc-client.port}"

add support for multiple property injection

Hi @maciejwalkowiak

I would like to suggest one enhancement: introduction of multiple property mapping (instead of a single one):

This leads to a simplified setup, for example:

current, complex approach:

@EnableWireMock({
    @ConfigureWireMock(name = "product-aggregates-service", property = "app.client-apis.product-aggregates.base-path", configurationCustomizers = {WireMockCustomizer.class}),
    @ConfigureWireMock(name = "participations-service", property = "app.client-apis.participations.base-path", configurationCustomizers = {WireMockCustomizer.class}),
    @ConfigureWireMock(name = "businesspartners-service", property = "app.client-apis.businesspartners.base-path", configurationCustomizers = {WireMockCustomizer.class}),
    @ConfigureWireMock(name = "usageinformations-service", property = "app.client-apis.usage-informations.base-path", configurationCustomizers = {WireMockCustomizer.class})
})

new, simplified aproach:

@EnableWireMock({
    @ConfigureWireMock(name = "services",
         property = {
            "app.client-apis.product-aggregates.base-path"
            "app.client-apis.participations.base-path",      
            "app.client-apis.businesspartners.base-path",
            "app.client-apis.usage-informations.base-path"
         },
        configurationCustomizers = {WireMockCustomizer.class})
})

If you are convinced by that feature, I can try to make a PR

Support wiremock configuration options

Currently an instance of WireMockServer is created which you cannot configure further. Annotations don't provide a way to configure options too. What if I want to change transfer encoding or gzip options?

Support for WireMock default instance

I'm looking at how to replace spring-cloud-contract-wiremock with wiremock-spring-boot in one of my projects (scordio/spring-batch-notion#25) and I noticed the configuration becomes a little more verbose.

Specifically:

  • @AutoConfigureWireMock(port = 0) is replaced by @EnableWireMock(@ConfigureWireMock(name = "wiremock", property = "wiremock.server.url"))
  • Wherever WireMock static methods like givenThat were used, I must use instead a WireMockServer instance injected via @InjectWireMock("wiremock")

In my use case, I don't need custom configurations or the support of multiple instances per test execution, therefore relying on the WireMock default instance would be enough.

I'd like to propose an enhancement where:

  • The declaration of @EnableWireMock without any additional @ConfigureWireMock sets up the WireMock default instance on a random available port
  • The port would be injected into a wiremock.server.port property, mimicking Spring Could Contract WireMock for some convention over configuration
  • Wiremock static methods work with the default instance and without the need to inject it via @InjectWireMock (although nothing should prevent its usage)

If you agree with the idea, I'll be happy to investigate it.

Not working for Nested test classes

First off, great lib! Thanks!

I'm using @Nested for some of my test classes, but the this lib does not seems to handle it very well:

@EnableWireMock({
        @ConfigureWireMock(name = "external-api", property = "application.external-api.base-url")
})
public class ExternalServiceTest extends IntegrationTest {
    @InjectWireMock("external-api")
    WireMockServer externalApiMock;

    @Nested
    @DisplayName("Test Something")
    public class TestSomething {
        @Test
        public void test1() {
            externalApiMock.stubFor(post(urlPathEqualTo("/test")).willReturn(ok())); // Throws a NullPointerException
        }
    }
}

However moving the annotation to the nested class works fine. So, not a blocker. However, it would be nice if this worked with nested classes in the example above.

Allow mappings from given location on filesystem

Looks like it only supports mappings from classpath locations. spring-cloud-contract supports having them in any folder, would ease migration to this library if we don't have to moven them. Would not be a problem if we had only a few applications, but we have about 100 so this would help us.

`WireMock` naming collision

There is a great likelihood that both com.maciejwalkowiak.wiremock.spring.WireMock and com.github.tomakehurst.wiremock.client.WireMock classes will be imported into a single file which forces user to use one of them with full qualified name.

For example:

@com.maciejwalkowiak.wiremock.spring.WireMock("user-service")
private WireMockServer wiremock;

To avoid breaking change, there should be a new annotation introduced that will behave exactly the same as com.maciejwalkowiak.wiremock.spring.WireMock just with a different name.

Ideas:

  • @InjectWireMock
  • @WireMocked
  • @WireMockInstance

Suggestions for name very welcome!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.