Skip to content
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

Question: Same/similar fluent interface for in process and admin client API #172

Closed
seanamosw opened this issue Aug 3, 2018 · 11 comments
Closed

Comments

@seanamosw
Copy link

The API for stubbing and finding requests in process is done with a fluent API while using the admin client uses object construction. This can make it challenging to work with WireMock in containers or out of process.

In process:

var server = FluentMockServer.Start();

var id = Guid.NewGuid();

var request = 
    Request.Create()
        .UsingPut()
        .WithPath("/test")
        .WithBody($"*{id}*");
        
server.Given(request)
    .RespondWith(
        Response.Create()
            .WithStatusCode(200)
            .WithBody("Test!!"));
...

var logs = server.FindLogEntries(request);

The same with admin interface:

var admin = RestEase.RestClient.For<IFluentMockServerAdmin>("http:https://mock-container");

var id = Guid.NewGuid();

var requestModel = new RequestModel
{
    Methods = new [] { "put" },
    Path = "/test",
    Body = new BodyModel { Matcher = new MatcherModel
    {
        Name = "WildcardMatcher",
        Pattern = $"*{id}*"
    }}
};

await admin.PostMappingAsync(new MappingModel
{
    Request = requestModel,
    Response = new ResponseModel
    {
        StatusCode = 200,
        Body = "Test!!"
    }
});

...

var logs = await admin.FindRequestsAsync(requestModel);

The more complex the request/response model the more verbose it becomes.
The difference I think stems from the builders not creating a serializable model.

Possible solutions/improvements

1. Request/Response model builders are changed to produce serializable models.

There is already code to "interpret" Request/Response/Mapping models.

Example (proposed API is not important, the idea is):

var requestModel = RequestModelBuilder.xxx(); // builder that creates RequestModel
var responseModel = ResponseModelBuilder.xxx(); // builder that create ResponseModel

server.Given(requestModel)
      .RespondsWith(responseModel); // creates and interprets MappingModel

admin.PostMappingAsync(
    MappingModel.Given(requestModel)
                .RespondsWith(responseModel));
Pros
  • Can fluently construct serializable and wire friendly mappings
  • Unified API for both in process and remote
Cons
  • Breaking change
  • Would probably lose the ability to use lambdas in some builder methods like WithBody

2. Two fluent interfaces, add Given overload to FluentMockServer

The idea is that the current fluent interface is left intact and a second fluent interface is introduced that can create Request/Response/Mapping models.

Pros
  • No breaking change
  • Retain the ability to use in process lambdas
Cons
  • Two fluent interfaces to maintain
@StefH
Copy link
Collaborator

StefH commented Aug 4, 2018

The fluent interface is mostly designed to be:

  1. used in unit-testing
  2. used for some complex mocking functionality in a standalone which cannot be achieved by just running a server and providing the mappings via the admin REST interface.

The admin REST interface can be used from any tool (postman, soapui, ...) or programming lamguage (C#, java, javascript, ...).
The current C# client interface (build with RestEase) is just a very convenient interface for developers who what to access the admin REST interface using c# & dotnet.

So option 1 would not be my preference.

And about option 2, I wonder how the fluent interface should look?

Do you mean something like:

var requestModel = new RequestModel
{
   // manually define all properties here in code
};

var responseModel = new ResponseModel
{
   // manually define all properties here in code
};

var server = FluentMockServer.Start();

server.Given(requestModel).RespondWith(responseModel);

@seanamosw
Copy link
Author

To clarify, this idea is sort of a middle ground with what the Java Wiremock allows. You can point the java client API at a remote Wiremock process and leverage the fluent interface against it. In their case, the API was designed to treat Wiremock as always out of process, even if it is in process.

My immediate use case is using Wiremock.Net in C# integration tests running in containers. This means Wiremock is always out of process. Typically some stub setup needs to be done at the beginning of each test and possibly verifying outbound calls were made. At the moment this needs to be done by constructing the Model objects.

It works but being able to use a fluent interface to construct the Request/Response model would be a significant quality of life improvement.

@seanamosw
Copy link
Author

In an ideal world, something similar to this would possible:

var requestModel =
    Request.Create()
        .UsingGet()
        .WithUrl("/test");

var responseModel =
    Response.Create()
        .WithStatusCode(200);

await admin.PostMappingAsync(new MappingModel
{
    Request = requestModel,
    Response = responseModel
});

// being able to use the same fluent interface between remote and in process
server.Given(requestModel).RespondWith(responseModel);

@StefH
Copy link
Collaborator

StefH commented Aug 5, 2018

a]
The new interface builder would have to look like:

var requestModel =
    RequestModelBuilder.Create()
        .UsingGet()
        .WithUrl("/test")
        .Build();

This means that the whole code from RequestBuilders needs to be copied.

I was hoping that I could use some autogenerating for that: https://github.com/ScottLilly/FluentInterfaceCreator, but this tool is not ready yet.

So for this reason, I'll not implement this new interface builder, it's too much work and I need to keep 2 interfaces in sync.

b]
Updating the current fluent interface to understand

server.Given(requestModel).RespondWith(responseModel);

can be done I think, not that much changes needed.

Maybe you can form my project, start a new branch and make a PR for this?

@seanamosw
Copy link
Author

a. I agree, maintaining two fluent interfaces and keeping them in sync is a burden.
Without a breaking change, two fluent interfaces to achieve this would be unavoidable.

Another option that could work is adding a separate lib, eg. WireMock.Net.ModelBuilders That could have the fluent interface for building the request/response model builders without polluting the main library with two fluent interfaces. I'd be happy to implement and maintain that.

b. I can do that.

@StefH
Copy link
Collaborator

StefH commented Aug 6, 2018

a] Maybe it's a good idea that I create this project under the https://github.com/WireMock-Net organization and give you (and me) access to that.

Also the NuGet package should be registered to both you and me if possible.

b] OK

@StefH
Copy link
Collaborator

StefH commented Aug 6, 2018

a] I did send invite to you, if you accept, I can give you access to this project.
The license is apache 2.0 ; but we can also change this into MIT? I don't know the real difference and what's better.

@seanamosw
Copy link
Author

Thanks.
MIT is often a go to license, simple and permissive. It doesn't have the "State Changes" clause of Apache 2.0.

@StefH
Copy link
Collaborator

StefH commented Aug 7, 2018

I've also added you as contributor to that new project.

Can this issue be closed?

(New issues or ideas can also be added to that project.)

@seanamosw
Copy link
Author

Yes, I think we have a way forward so any further discussion can be moved there.

@StefH StefH closed this as completed Aug 7, 2018
@StefH StefH changed the title Feature: Same/similar fluent interface for in process and admin client API Question: Same/similar fluent interface for in process and admin client API Aug 8, 2018
@StefH
Copy link
Collaborator

StefH commented Aug 9, 2020

@seanamosw
Did you continue on the code in the develop-branch from the https://github.com/WireMock-Net/WireMock.Net.ModelBuilders/tree/develop/ project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants