Unexpected state API behaviour around unset state #269

Closed
opened 2025-12-29 08:25:10 +01:00 by adam · 6 comments
Owner

Originally created by @arturohernandez10 on GitHub (May 1, 2020).

The following code would appear to leave the state unchanged. But after this is matched in runtime. The state will be reset to "nothing" like it had never been set.

            _server
                .Given( Request.Create().UsingGet().WithPath( new ExactMatcher("/StateUnchanged")))
                .InScenario("default")
                .WhenStateIs("State2")
                .RespondWith( Response.Create().WithBody("State reset to nothing"));

Leading to the following code that is unnecessarily verbose. Particularly with a fluent API. Where the intention seems to underspecify a mock API. And leave the tool to make educated choices.

            _server
                .Given( Request.Create().UsingGet().WithPath( new ExactMatcher("/StateUnchanged")))
                .InScenario("default")
                .WhenStateIs("State2")
                .WillSetStateTo("State2")
                .RespondWith( Response.Create().WithBody("State is still State2"));
Originally created by @arturohernandez10 on GitHub (May 1, 2020). The following code would appear to leave the state unchanged. But after this is matched in runtime. The state will be reset to "nothing" like it had never been set. ``` cs _server .Given( Request.Create().UsingGet().WithPath( new ExactMatcher("/StateUnchanged"))) .InScenario("default") .WhenStateIs("State2") .RespondWith( Response.Create().WithBody("State reset to nothing")); ``` Leading to the following code that is unnecessarily verbose. Particularly with a fluent API. Where the intention seems to underspecify a mock API. And leave the tool to make educated choices. ``` c# _server .Given( Request.Create().UsingGet().WithPath( new ExactMatcher("/StateUnchanged"))) .InScenario("default") .WhenStateIs("State2") .WillSetStateTo("State2") .RespondWith( Response.Create().WithBody("State is still State2")); ```
adam added the question label 2025-12-29 08:25:10 +01:00
adam closed this issue 2025-12-29 08:25:10 +01:00
Author
Owner

@StefH commented on GitHub (May 11, 2020):

Can you take a look at the Wiki : https://github.com/WireMock-Net/WireMock.Net/wiki/Scenarios-and-States and check if this is working for you?

@StefH commented on GitHub (May 11, 2020): Can you take a look at the Wiki : https://github.com/WireMock-Net/WireMock.Net/wiki/Scenarios-and-States and check if this is working for you?
Author
Owner

@StefH commented on GitHub (Aug 1, 2020):

@arturohernandez10

Does the wiki help you using Scenarios and States? Or do you still have some questions?

@StefH commented on GitHub (Aug 1, 2020): @arturohernandez10 Does the wiki help you using Scenarios and States? Or do you still have some questions?
Author
Owner

@StefH commented on GitHub (Aug 25, 2020):

@arturohernandez10

Did you find a solution in the WIKI?

@StefH commented on GitHub (Aug 25, 2020): @arturohernandez10 Did you find a solution in the WIKI?
Author
Owner

@arturohernandez10 commented on GitHub (Aug 28, 2020):

The wiki is not very explicit. No. the issue is: you have to specify the next state. Otherwise the state is cleared. The example agrees with not_set -> A , A -> B, B -> not_set. But in many state driven definitions, it is perfectly valid to specify behavior on a given state. Following you wiki example, if a delete was not valid when the to-do list was just started. You might want to do this:

	.Given(Request.Create()
		.WithPath("/todo/items")
		.UsingDelete())
	.InScenario("To do list")
	.WhenStateIs("TodoList State Started")
	.RespondWith(Response.Create()
		.WithStatusCode(400));

But have one more like this and the test would not work, and you may be thoroughly confused as of why. It seems perfectly normal. You are in the TodoList State Started and the To do list scenario. Why is this not working? Well, because you actually specified .WhenStateIs("TodoList State Started").WillSetStateTo(<<implicit_state_not_set_state>>) If the idea is for users to write this request/response expressions or every single test case; then it makes sense. But if you also want to support the creation of testing fixtures, that can be reused by a broader set of use cases. Then the user has to write .WhenStateIs("TodoList State Started").WillSetStateTo("TodoList State Started") which I don't think is intuitive. maybe you need to add some other method like .WhenStateWillContinueToBe("TodoList State Started") or something more creative.

Or even better add a WhenStateIsV2 and WillSetStateTo2 that don't set the state to not_set. Again creativity on naming is required.

Thanks for the question!!!

@arturohernandez10 commented on GitHub (Aug 28, 2020): The wiki is not very explicit. No. the issue is: you __have to__ specify the next state. Otherwise the state is cleared. The example agrees with not_set -> A , A -> B, B -> not_set. But in many state driven definitions, it is perfectly valid to specify behavior on a given state. Following you wiki example, if a delete was not valid when the to-do list was just started. You might want to do this: ```_server .Given(Request.Create() .WithPath("/todo/items") .UsingDelete()) .InScenario("To do list") .WhenStateIs("TodoList State Started") .RespondWith(Response.Create() .WithStatusCode(400)); ``` But have one more like this and the test would not work, and you may be thoroughly confused as of why. It seems perfectly normal. You are in the `TodoList State Started` and the `To do list` scenario. Why is this not working? Well, because you actually specified `.WhenStateIs("TodoList State Started").WillSetStateTo(<<implicit_state_not_set_state>>)` If the idea is for users to write this request/response expressions or every single test case; then it makes sense. But if you also want to support the creation of testing fixtures, that can be reused by a broader set of use cases. Then the user has to write `.WhenStateIs("TodoList State Started").WillSetStateTo("TodoList State Started")` which I don't think is intuitive. maybe you need to add some other method like `.WhenStateWillContinueToBe("TodoList State Started")` or something more creative. Or even better add a `WhenStateIsV2` and `WillSetStateTo2` that don't set the state to `not_set`. Again creativity on naming is required. Thanks for the question!!!
Author
Owner

@StefH commented on GitHub (Aug 30, 2020):

@arturohernandez10
Now I understand your question.

Actually, your question looks a lot like this issue : https://github.com/WireMock-Net/WireMock.Net/issues/494

Which was solved by adding an times parameter to the WillSetStateTo method:
IRespondWithAProvider WillSetStateTo(string state, int? times = 1);

In your case, you can set the value for the times to Int32.MaxValue.

I think this solves your issue. Can you take a look and test ?

Wiki has been updated : The number of times this match should be matched before the state will be changed to the specified one. Default value is 1.

@StefH commented on GitHub (Aug 30, 2020): @arturohernandez10 Now I understand your question. Actually, your question looks a lot like this issue : https://github.com/WireMock-Net/WireMock.Net/issues/494 Which was solved by adding an **times** parameter to the **WillSetStateTo** method: `IRespondWithAProvider WillSetStateTo(string state, int? times = 1);` In your case, you can set the value for the **times** to `Int32.MaxValue`. I think this solves your issue. Can you take a look and test ? Wiki has been updated : The number of times this match should be matched before the state will be changed to the specified one. Default value is 1.
Author
Owner

@arturohernandez10 commented on GitHub (Sep 4, 2020):

@StefH

Awesome!! I like this library, that comment may have spared me from some confusion. It may help someone else. Next time I use this tool, I'll create an extension method as a shortcut for .WhenStateIs("x").WillSetStateTo("x") and I'll post it here if anyone prefers to use it.

Thanks!

@arturohernandez10 commented on GitHub (Sep 4, 2020): @StefH Awesome!! I like this library, that comment may have spared me from some confusion. It may help someone else. Next time I use this tool, I'll create an extension method as a shortcut for `.WhenStateIs("x").WillSetStateTo("x")` and I'll post it here if anyone prefers to use it. Thanks!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#269