mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-26 02:51:04 +01:00
* Move ScenarioState to Abstractions and add IScenarioStateStore interface ScenarioState is moved to the Abstractions project so it can be referenced by the new IScenarioStateStore interface. The interface defines the contract for storing and retrieving scenario states, enabling distributed implementations. * Add InMemoryScenarioStateStore default implementation Wraps ConcurrentDictionary with OrdinalIgnoreCase comparer, preserving exact current behavior. The Update method encapsulates read-modify-write so distributed implementations can make it atomic. * Wire IScenarioStateStore into middleware options, settings, and consumers Replace direct ConcurrentDictionary<string, ScenarioState> usage with IScenarioStateStore across all consumer files. The store is injectable via WireMockServerSettings.ScenarioStateStore, defaulting to the InMemoryScenarioStateStore for backward compatibility. * Add FileBasedScenarioStateStore for persistent scenario state In-memory ConcurrentDictionary backed by JSON file persistence in __admin/scenarios/. Reads from cache, mutations write through to disk. Constructor loads existing state from disk on startup. * Make ScenarioStateStore non-nullable with default InMemoryScenarioStateStore Move InMemoryScenarioStateStore from WireMock.Net.Minimal to WireMock.Net.Shared so it lives alongside WireMockServerSettings. This allows WireMockServerSettings.ScenarioStateStore to be non-nullable with a default value, following the same pattern as DefaultJsonSerializer. The null-coalescing fallback in WireMockMiddlewareOptionsHelper is no longer needed.
158 lines
4.4 KiB
C#
158 lines
4.4 KiB
C#
// Copyright © WireMock.Net
|
|
|
|
using WireMock.Handlers;
|
|
using Xunit;
|
|
|
|
namespace WireMock.Net.Tests.Handlers;
|
|
|
|
public class InMemoryScenarioStateStoreTests
|
|
{
|
|
private readonly InMemoryScenarioStateStore _sut = new();
|
|
|
|
[Fact]
|
|
public void TryAdd_ShouldAddNewScenario()
|
|
{
|
|
var state = new ScenarioState { Name = "scenario1" };
|
|
|
|
_sut.TryAdd("scenario1", state).Should().BeTrue();
|
|
|
|
_sut.ContainsKey("scenario1").Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void TryAdd_ShouldReturnFalse_WhenScenarioAlreadyExists()
|
|
{
|
|
var state = new ScenarioState { Name = "scenario1" };
|
|
_sut.TryAdd("scenario1", state);
|
|
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1" }).Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGet_ShouldReturnTrue_WhenExists()
|
|
{
|
|
var state = new ScenarioState { Name = "scenario1", NextState = "state2" };
|
|
_sut.TryAdd("scenario1", state);
|
|
|
|
_sut.TryGet("scenario1", out var result).Should().BeTrue();
|
|
|
|
result.Should().NotBeNull();
|
|
result!.NextState.Should().Be("state2");
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGet_ShouldReturnFalse_WhenNotExists()
|
|
{
|
|
_sut.TryGet("nonexistent", out var result).Should().BeFalse();
|
|
result.Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void GetAll_ShouldReturnAllScenarios()
|
|
{
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1" });
|
|
_sut.TryAdd("scenario2", new ScenarioState { Name = "scenario2" });
|
|
|
|
var result = _sut.GetAll();
|
|
|
|
result.Should().HaveCount(2);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetAll_ShouldReturnEmpty_WhenNoScenarios()
|
|
{
|
|
_sut.GetAll().Should().BeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_ShouldModifyExistingScenario()
|
|
{
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1", Counter = 0 });
|
|
|
|
var result = _sut.Update("scenario1", s => { s.Counter = 5; s.NextState = "state2"; });
|
|
|
|
result.Should().NotBeNull();
|
|
result!.Counter.Should().Be(5);
|
|
result.NextState.Should().Be("state2");
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_ShouldReturnNull_WhenNotExists()
|
|
{
|
|
_sut.Update("nonexistent", s => { s.Counter = 5; }).Should().BeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void AddOrUpdate_ShouldAddNewScenario()
|
|
{
|
|
var result = _sut.AddOrUpdate(
|
|
"scenario1",
|
|
_ => new ScenarioState { Name = "scenario1", NextState = "added" },
|
|
(_, current) => { current.NextState = "updated"; return current; }
|
|
);
|
|
|
|
result.NextState.Should().Be("added");
|
|
}
|
|
|
|
[Fact]
|
|
public void AddOrUpdate_ShouldUpdateExistingScenario()
|
|
{
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1", NextState = "initial" });
|
|
|
|
var result = _sut.AddOrUpdate(
|
|
"scenario1",
|
|
_ => new ScenarioState { Name = "scenario1", NextState = "added" },
|
|
(_, current) => { current.NextState = "updated"; return current; }
|
|
);
|
|
|
|
result.NextState.Should().Be("updated");
|
|
}
|
|
|
|
[Fact]
|
|
public void TryRemove_ShouldRemoveExistingScenario()
|
|
{
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1" });
|
|
|
|
_sut.TryRemove("scenario1").Should().BeTrue();
|
|
_sut.ContainsKey("scenario1").Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void TryRemove_ShouldReturnFalse_WhenNotExists()
|
|
{
|
|
_sut.TryRemove("nonexistent").Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Clear_ShouldRemoveAllScenarios()
|
|
{
|
|
_sut.TryAdd("scenario1", new ScenarioState { Name = "scenario1" });
|
|
_sut.TryAdd("scenario2", new ScenarioState { Name = "scenario2" });
|
|
|
|
_sut.Clear();
|
|
|
|
_sut.GetAll().Should().BeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void ContainsKey_ShouldBeCaseInsensitive()
|
|
{
|
|
_sut.TryAdd("Scenario1", new ScenarioState { Name = "Scenario1" });
|
|
|
|
_sut.ContainsKey("scenario1").Should().BeTrue();
|
|
_sut.ContainsKey("SCENARIO1").Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void TryGet_ShouldBeCaseInsensitive()
|
|
{
|
|
_sut.TryAdd("Scenario1", new ScenarioState { Name = "Scenario1", NextState = "state2" });
|
|
|
|
_sut.TryGet("scenario1", out var result1).Should().BeTrue();
|
|
result1!.NextState.Should().Be("state2");
|
|
|
|
_sut.TryGet("SCENARIO1", out var result2).Should().BeTrue();
|
|
result2!.NextState.Should().Be("state2");
|
|
}
|
|
}
|