diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs
index bebff0e1..94315092 100644
--- a/src/WireMock.Net/Mapping.cs
+++ b/src/WireMock.Net/Mapping.cs
@@ -34,6 +34,17 @@ namespace WireMock
///
public int Priority { get; }
+ ///
+ /// Execution state condition for the current mapping.
+ ///
+ public object ExecutionConditionState { get; }
+
+ ///
+ /// The next state which will be signaled after the current mapping execution.
+ /// In case the value is null state will not be changed.
+ ///
+ public object NextState { get; }
+
///
/// The Request matcher.
///
@@ -53,8 +64,25 @@ namespace WireMock
/// The provider.
/// The priority for this mapping.
public Mapping(Guid guid, [CanBeNull] string title, IRequestMatcher requestMatcher, IResponseProvider provider, int priority)
+ : this(guid, title, requestMatcher, provider, priority, null, null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The unique identifier.
+ /// The unique title (can be null_.
+ /// The request matcher.
+ /// The provider.
+ /// The priority for this mapping.
+ /// State in which the current mapping can occur. Happens if not null
+ /// The next state which will occur after the current mapping execution. Happens if not null
+ public Mapping(Guid guid, [CanBeNull] string title, IRequestMatcher requestMatcher, IResponseProvider provider, int priority, object executionConditionState, object nextState)
{
Priority = priority;
+ ExecutionConditionState = executionConditionState;
+ NextState = nextState;
Guid = guid;
Title = title;
RequestMatcher = requestMatcher;
diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs
index 529082d6..ab3c13d3 100644
--- a/src/WireMock.Net/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs
@@ -24,15 +24,19 @@ namespace WireMock.Owin
private readonly OwinRequestMapper _requestMapper = new OwinRequestMapper();
private readonly OwinResponseMapper _responseMapper = new OwinResponseMapper();
+ public object State { get; private set; }
+
#if !NETSTANDARD
public WireMockMiddleware(OwinMiddleware next, WireMockMiddlewareOptions options) : base(next)
{
_options = options;
+ State = null;
}
#else
public WireMockMiddleware(RequestDelegate next, WireMockMiddlewareOptions options)
{
_options = options;
+ State = null;
}
#endif
@@ -51,6 +55,7 @@ namespace WireMock.Owin
try
{
var mappings = _options.Mappings
+ .Where(m => object.Equals(m.ExecutionConditionState, State))
.Select(m => new
{
Mapping = m,
@@ -107,6 +112,7 @@ namespace WireMock.Owin
}
response = await targetMapping.ResponseToAsync(request);
+ State = targetMapping.NextState;
}
catch (Exception ex)
{
diff --git a/src/WireMock.Net/Properties/AssemblyInfo.cs b/src/WireMock.Net/Properties/AssemblyInfo.cs
index 60a444e7..e6452c0f 100644
--- a/src/WireMock.Net/Properties/AssemblyInfo.cs
+++ b/src/WireMock.Net/Properties/AssemblyInfo.cs
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
-[assembly: InternalsVisibleTo("WireMock.Net.StandAlone")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("WireMock.Net.StandAlone")]
+[assembly: InternalsVisibleTo("WireMock.Net.Tests")]
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs
index 33a31579..93fe0e5b 100644
--- a/src/WireMock.Net/Server/IRespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs
@@ -40,5 +40,19 @@ namespace WireMock.Server
///
/// The provider.
void RespondWith(IResponseProvider provider);
+
+ ///
+ /// Execute this respond only in case the current state is equal to specified one
+ ///
+ /// Any object which identifies the current state
+ /// The .
+ IRespondWithAProvider WhenStateIs(object state);
+
+ ///
+ /// Once this mapping is executed the state will be changed to specified one
+ ///
+ /// Any object which identifies the new state
+ /// The .
+ IRespondWithAProvider WillSetStateTo(object state);
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Server/RespondWithAProvider.cs b/src/WireMock.Net/Server/RespondWithAProvider.cs
index 843a5448..afde9558 100644
--- a/src/WireMock.Net/Server/RespondWithAProvider.cs
+++ b/src/WireMock.Net/Server/RespondWithAProvider.cs
@@ -12,6 +12,9 @@ namespace WireMock.Server
private Guid? _guid;
private string _title;
+ private object _executionConditionState = null;
+ private object _nextState = null;
+
///
/// The _registration callback.
///
@@ -42,7 +45,19 @@ namespace WireMock.Server
public void RespondWith(IResponseProvider provider)
{
var mappingGuid = _guid ?? Guid.NewGuid();
- _registrationCallback(new Mapping(mappingGuid, _title, _requestMatcher, provider, _priority));
+ _registrationCallback(new Mapping(mappingGuid, _title, _requestMatcher, provider, _priority, _executionConditionState, _nextState));
+ }
+
+ public IRespondWithAProvider WhenStateIs(object state)
+ {
+ _executionConditionState = state;
+ return this;
+ }
+
+ public IRespondWithAProvider WillSetStateTo(object state)
+ {
+ _nextState = state;
+ return this;
}
///
diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs
index a8875a87..a220f8ab 100644
--- a/test/WireMock.Net.Tests/FluentMockServerTests.cs
+++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs
@@ -407,7 +407,7 @@ namespace WireMock.Net.Tests
var requestLoggedB = _server.LogEntries.Last();
Check.That(requestLoggedB.RequestMessage.Path).EndsWith("/foo3");
- }
+ }
public void Dispose()
{
diff --git a/test/WireMock.Net.Tests/StatefulBehaviorTests.cs b/test/WireMock.Net.Tests/StatefulBehaviorTests.cs
new file mode 100644
index 00000000..db24aeeb
--- /dev/null
+++ b/test/WireMock.Net.Tests/StatefulBehaviorTests.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using NFluent;
+using WireMock.RequestBuilders;
+using WireMock.ResponseBuilders;
+using WireMock.Server;
+using Xunit;
+
+namespace WireMock.Net.Tests
+{
+ public class StatefulBehaviorTests : IDisposable
+ {
+ private FluentMockServer _server;
+
+ [Fact]
+ public async Task Should_skip_non_relevant_states()
+ {
+ // given
+ _server = FluentMockServer.Start();
+
+ _server
+ .Given(Request.Create()
+ .WithPath("/foo")
+ .UsingGet())
+ .WhenStateIs("Test state")
+ .RespondWith(Response.Create()
+ .WithStatusCode(200)
+ .WithBody(@"{ msg: ""Hello world!""}"));
+
+ // when
+ var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
+
+ // then
+ Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound);
+ }
+
+ [Fact]
+ public async Task Should_process_request_if_equals_state()
+ {
+ // given
+ _server = FluentMockServer.Start();
+
+ _server
+ .Given(Request.Create()
+ .WithPath("/foo")
+ .UsingGet())
+ .WillSetStateTo("Test state")
+ .RespondWith(Response.Create()
+ .WithStatusCode(200)
+ .WithBody(@"No state msg"));
+
+ _server
+ .Given(Request.Create()
+ .WithPath("/foo")
+ .UsingGet())
+ .WhenStateIs("Test state")
+ .RespondWith(Response.Create()
+ .WithStatusCode(200)
+ .WithBody(@"Test state msg"));
+
+ // when
+ var responseNoState = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
+ var responseWithState = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
+
+ // then
+ Check.That(responseNoState).Equals("No state msg");
+ Check.That(responseWithState).Equals("Test state msg");
+ }
+
+ public void Dispose()
+ {
+ _server?.Dispose();
+ }
+ }
+}
diff --git a/test/WireMock.Net.Tests/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/WireMockMiddlewareTests.cs
new file mode 100644
index 00000000..13abf057
--- /dev/null
+++ b/test/WireMock.Net.Tests/WireMockMiddlewareTests.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Owin;
+using Moq;
+using NFluent;
+using WireMock.Owin;
+using Xunit;
+
+namespace WireMock.Net.Tests
+{
+ public class WireMockMiddlewareTests
+ {
+ private readonly ObjectMother _objectMother = new ObjectMother();
+
+ [Fact]
+ public void Should_have_default_state_as_null()
+ {
+ // given
+
+ // when
+ var sut = _objectMother.Create();
+
+ // then
+ Check.That(sut.State).IsNull();
+ }
+
+ internal class ObjectMother
+ {
+ public Mock OwinMiddleware { get; set; }
+ public Mock OwinContext { get; set; }
+ public WireMockMiddlewareOptions WireMockMiddlewareOptions { get; set; }
+
+ public ObjectMother()
+ {
+ OwinContext = new Mock();
+ OwinMiddleware = new Mock(null);
+ WireMockMiddlewareOptions = new WireMockMiddlewareOptions();
+ }
+
+ public WireMockMiddleware Create()
+ {
+ return new WireMockMiddleware(OwinMiddleware.Object, WireMockMiddlewareOptions);
+ }
+ }
+ }
+}