Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions DevProxy.Integration.Tests/GenerationPluginsIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,49 @@ public async Task MockGenerator_WritesMockFile()
}
}

[Fact]
public async Task MockGenerator_PreservesRecordedOrderForSameUrl()
{
var plugin = new MockGeneratorPlugin(NullLogger<MockGeneratorPlugin>.Instance, Watch);

// enough entries to exceed the insertion-sort threshold of an unstable sort
const int count = 40;
var logs = Enumerable.Range(0, count)
.Select(i => TestExchange
.Request("GET", i % 2 == 0 ? "https://api.contoso.com/a" : "https://api.contoso.com/b")
.WithResponse(
HttpStatusCode.OK,
headers: [("Content-Type", "application/json")],
body: $$"""{ "seq": {{i}} }""")
.AsRequestLog(MessageType.InterceptedResponse))
.ToList();

var args = Recording(logs);
var dir = await InTempCwdAsync(() => plugin.AfterRecordingStopAsync(args, CancellationToken.None));
try
{
var mockFile = dir.GetFiles("mocks-*.json").Single();
using var doc = JsonDocument.Parse(await File.ReadAllTextAsync(mockFile.FullName));
var mocks = doc.RootElement.GetProperty("mocks").EnumerateArray()
.Select(m => (
Url: m.GetProperty("request").GetProperty("url").GetString(),
Seq: m.GetProperty("response").GetProperty("body").GetProperty("seq").GetInt32()))
.ToArray();

Assert.Equal(count, mocks.Length);

var expected = Enumerable.Range(0, count).Where(i => i % 2 == 1)
.Select(i => ("https://api.contoso.com/b", i))
.Concat(Enumerable.Range(0, count).Where(i => i % 2 == 0)
.Select(i => ("https://api.contoso.com/a", i)));
Assert.Equal(expected, mocks.Select(m => (m.Url!, m.Seq)));
}
finally
{
dir.Delete(recursive: true);
}
}

[Fact]
public async Task HttpFileGenerator_WritesHttpFile()
{
Expand Down
6 changes: 4 additions & 2 deletions DevProxy.Plugins/Generation/MockGeneratorPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ request.Context.Session is null ||
}

Logger.LogDebug("Sorting mocks...");
// sort mocks descending by url length so that most specific mocks are first
mocks.Sort((a, b) => string.CompareOrdinal(b.Request!.Url, a.Request!.Url));
// group mocks by URL (descending ordinal order) for readability. Generated
// mocks use exact URLs, so this order doesn't affect matching. The sort is
// stable so that repeated requests to the same URL keep their recorded order.
mocks = [.. mocks.OrderByDescending(m => m.Request!.Url, StringComparer.Ordinal)];

var mocksFile = new MockResponseConfiguration { Mocks = mocks };

Expand Down
Loading