Compare commits

...

14 Commits
1.6.3 ... 1.6.5

Author SHA1 Message Date
Stef Heyenrath
edbc7aeb5c 1.6.5 2024-09-28 10:26:38 +02:00
Stef Heyenrath
42306d1864 Add WireMock.Net.AspNetCore.Middleware (#1175)
* Add WireMock.Net.AspNetCore.Middleware

* .

* WireMock.Net.Middleware.Tests

* .

* X-WireMock-Response-Delay
2024-09-27 20:39:57 +02:00
Stef Heyenrath
c57590b2ba Set <SonarQubeExclude>true</SonarQubeExclude> in test projects (#1183) 2024-09-27 20:06:22 +02:00
Stef Heyenrath
dca3fd0260 WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux (#1181)
* WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux

* ...

* .

* WithBindMount

* fix

* r

* .
2024-09-27 19:10:51 +02:00
Jason Landbridge
95994421ae pass in the request when no matching is found to the warn logger (#1182) 2024-09-27 19:10:39 +02:00
Stef Heyenrath
697411555a Update README.md (add WireMock.Net.TUnit) 2024-09-26 18:47:36 +02:00
Stef Heyenrath
f89f0fa466 1.6.4 2024-09-25 08:56:44 +02:00
Stef Heyenrath
b892e85d2a Add WireMock.Net.TUnit project (#1179)
* Add WireMock.Net.TUnit project

* fix

* .

* fix

* bd

* 0.1.812

* dotnet test

* 0.1.817

* cat

* type

* type2

* find

* -- --diagnostic

* --no-build

* fix?
2024-09-25 08:52:40 +02:00
Stef Heyenrath
836976ca19 Upgrade CS-Script to version 4.8.17 (#1178) 2024-09-20 15:20:38 +02:00
Stef Heyenrath
c845f73dd0 Unpin Testcontainers version and upgrade to version 3.10.0 (#1177) 2024-09-20 15:20:25 +02:00
Stef Heyenrath
2cbbef01ae Refactor some code (IBodyDataExtensions) 2024-09-20 13:52:45 +02:00
Ruxo
dd80fd7822 Attempt to fix JSON parsing of text/plain content type (#1172)
* UseContentType

* Fix unit tests

* Add a unit test and an integration test for the fix.

* Simplify body type checking with GetBodyType extension.

* Split IBodyDataExtension, and use imperative style instead of functional style

* Remove excessive null forgiving operators

* Adjust braces

---------

Co-authored-by: Ruxo Zheng <rz@just.sent.as>
2024-09-20 13:19:32 +02:00
Stef Heyenrath
527278e60c Update the .NET Aspire tests (#1170)
* Skip unit tests when Docker is not running in Linux container mode using DockerIsRunningInLinuxContainerModeFact

* IgnoreOnContinuousIntegrationFact
2024-09-10 16:14:05 +02:00
Stef Heyenrath
7d7f1f8fbb Allow mapping without Path or Url (#1169) 2024-09-09 20:48:09 +02:00
55 changed files with 1416 additions and 192 deletions

View File

@@ -20,7 +20,10 @@ jobs:
- uses: actions/checkout@v4
- name: 'Execute Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
run: |
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
linux-build-and-run:
name: Run Tests on Linux
@@ -33,7 +36,10 @@ jobs:
- uses: actions/checkout@v4
- name: 'Execute Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
run: |
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
- name: Install .NET Aspire workload
run: dotnet workload install aspire

View File

@@ -1,3 +1,20 @@
# 1.6.5 (28 September 2024)
- [#1175](https://github.com/WireMock-Net/WireMock.Net/pull/1175) - Add WireMock.Net.AspNetCore.Middleware [feature] contributed by [StefH](https://github.com/StefH)
- [#1181](https://github.com/WireMock-Net/WireMock.Net/pull/1181) - WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux [feature] contributed by [StefH](https://github.com/StefH)
- [#1182](https://github.com/WireMock-Net/WireMock.Net/pull/1182) - pass in the request when no matching is found to the warn logger [feature] contributed by [JasonLandbridge](https://github.com/JasonLandbridge)
# 1.6.4 (25 September 2024)
- [#1169](https://github.com/WireMock-Net/WireMock.Net/pull/1169) - Allow mapping without Path or Url [bug] contributed by [StefH](https://github.com/StefH)
- [#1170](https://github.com/WireMock-Net/WireMock.Net/pull/1170) - Update the .NET Aspire tests [feature] contributed by [StefH](https://github.com/StefH)
- [#1172](https://github.com/WireMock-Net/WireMock.Net/pull/1172) - Fix JSON parsing of text/plain content type [bug] contributed by [ruxo](https://github.com/ruxo)
- [#1177](https://github.com/WireMock-Net/WireMock.Net/pull/1177) - Unpin Testcontainers version and upgrade to version 3.10.0 [bug] contributed by [StefH](https://github.com/StefH)
- [#1178](https://github.com/WireMock-Net/WireMock.Net/pull/1178) - Upgrade CS-Script to version 4.8.17 [feature] contributed by [StefH](https://github.com/StefH)
- [#1179](https://github.com/WireMock-Net/WireMock.Net/pull/1179) - Add WireMock.Net.TUnit project [feature] contributed by [StefH](https://github.com/StefH)
- [#1146](https://github.com/WireMock-Net/WireMock.Net/issues/1146) - Bump Request CS-Script 4.8.13 to 4.8.17 [feature]
- [#1167](https://github.com/WireMock-Net/WireMock.Net/issues/1167) - Admin API fails to create a mapping with Request Header matching using WildCardMatcher [bug]
- [#1168](https://github.com/WireMock-Net/WireMock.Net/issues/1168) - Numbers in text/plain content is parsed as JSON. [bug]
- [#1176](https://github.com/WireMock-Net/WireMock.Net/issues/1176) - WireMock.NET TestContainer Dependency Constraint Issue [bug]
# 1.6.3 (07 September 2024)
- [#1165](https://github.com/WireMock-Net/WireMock.Net/pull/1165) - Fix listen on AnyIP for url 0.0.0.0 contributed by [cocoon](https://github.com/cocoon)
- [#1154](https://github.com/WireMock-Net/WireMock.Net/issues/1154) - Listen on all ips [bug]
@@ -42,9 +59,7 @@
# 1.5.60 (09 July 2024)
- [#1128](https://github.com/WireMock-Net/WireMock.Net/pull/1128) - Add Handlebars.Net.Helpers.Xslt [feature] contributed by [StefH](https://github.com/StefH)
- [#1130](https://github.com/WireMock-Net/WireMock.Net/pull/1130) - Add AdminPath to WireMockServerSettings [feature] contributed by [StefH](https://github.com/StefH)
- [#1131](https://github.com/WireMock-Net/WireMock.Net/pull/1131) - Add unit tests for AdminApiMappingBuilder [test] contributed by [StefH](https://github.com/StefH)
- [#1132](https://github.com/WireMock-Net/WireMock.Net/pull/1132) - Multipart Matcher Fix [bug] contributed by [rmeshksar](https://github.com/rmeshksar)
- [#1133](https://github.com/WireMock-Net/WireMock.Net/pull/1133) - Add unit tests for AdminApiMappingBuilder_ [test] contributed by [StefH](https://github.com/StefH)
- [#1134](https://github.com/WireMock-Net/WireMock.Net/pull/1134) - Remove some files and folders [refactor] contributed by [StefH](https://github.com/StefH)
- [#1119](https://github.com/WireMock-Net/WireMock.Net/issues/1119) - Error in RequestMessageMultiPartMatcher [bug]
- [#1121](https://github.com/WireMock-Net/WireMock.Net/issues/1121) - XML transformation [feature]
@@ -129,7 +144,6 @@
# 1.5.42 (09 December 2023)
- [#1023](https://github.com/WireMock-Net/WireMock.Net/pull/1023) - Fix Mapping[] for WireMock.Org REST API [bug] contributed by [StefH](https://github.com/StefH)
- [#1029](https://github.com/WireMock-Net/WireMock.Net/pull/1029) - Add ResponseWithHandlebarsDateTimeTests [test] contributed by [StefH](https://github.com/StefH)
- [#1031](https://github.com/WireMock-Net/WireMock.Net/pull/1031) - Calling Reset also resets the scenarios [bug] contributed by [StefH](https://github.com/StefH)
- [#1034](https://github.com/WireMock-Net/WireMock.Net/pull/1034) - Workaround for: Random.Generate Type=&quot;Long&quot; [bug] contributed by [StefH](https://github.com/StefH)
- [#1021](https://github.com/WireMock-Net/WireMock.Net/issues/1021) - GetAdminMappingsResult in WireMock.Org.Abstractions should contain list of mappings [bug]
@@ -138,12 +152,9 @@
# 1.5.41 (04 December 2023)
- [#1012](https://github.com/WireMock-Net/WireMock.Net/pull/1012) - GraphQL - custom scalar support [feature] contributed by [StefH](https://github.com/StefH)
- [#1018](https://github.com/WireMock-Net/WireMock.Net/pull/1018) - Add .NET 8 [feature] contributed by [StefH](https://github.com/StefH)
- [#1020](https://github.com/WireMock-Net/WireMock.Net/pull/1020) - Add Github Action [test] contributed by [StefH](https://github.com/StefH)
- [#984](https://github.com/WireMock-Net/WireMock.Net/issues/984) - GraphQL Schema validation with custom scalars [feature]
# 1.5.40 (07 November 2023)
- [#1009](https://github.com/WireMock-Net/WireMock.Net/pull/1009) - Add more tests for JmesPathMatchers and StringUtils.ParseMatchOperator [test] contributed by [StefH](https://github.com/StefH)
- [#1010](https://github.com/WireMock-Net/WireMock.Net/pull/1010) - Add unit tests for HttpClient with WebProxy [test] contributed by [StefH](https://github.com/StefH)
- [#1011](https://github.com/WireMock-Net/WireMock.Net/pull/1011) - GraphQL - add support for standard scalar types in the schema [feature] contributed by [StefH](https://github.com/StefH)
- [#1014](https://github.com/WireMock-Net/WireMock.Net/pull/1014) - FluentAssertions - WithBody and WithBodyAsJson and WithBodyAsBytes contributed by [StefH](https://github.com/StefH)
@@ -155,7 +166,6 @@
- [#1005](https://github.com/WireMock-Net/WireMock.Net/pull/1005) - Support for xml namespaces in XPathMatcher [feature] contributed by [cal-schleupen](https://github.com/cal-schleupen)
# 1.5.37 (27 September 2023)
- [#998](https://github.com/WireMock-Net/WireMock.Net/pull/998) - Add JmesPathMatcher UnitTests [test] contributed by [StefH](https://github.com/StefH)
- [#1004](https://github.com/WireMock-Net/WireMock.Net/pull/1004) - Fix MappingModel to map IgnoreCase and RejectOnMatch for Headers, Cookies and Parameters [bug] contributed by [StefH](https://github.com/StefH)
- [#1003](https://github.com/WireMock-Net/WireMock.Net/issues/1003) - Store Mapping per POST request ignores &quot;IgnoreCase&quot; property of HeaderModel [bug]
@@ -167,7 +177,6 @@
- [#1001](https://github.com/WireMock-Net/WireMock.Net/issues/1001) - SaveUnmatchedRequests stopped working [bug]
# 1.5.35 (19 August 2023)
- [#992](https://github.com/WireMock-Net/WireMock.Net/pull/992) - Add extra unit test for WithParam multiple values comma [test] contributed by [StefH](https://github.com/StefH)
- [#993](https://github.com/WireMock-Net/WireMock.Net/pull/993) - Update JSONPathMatcher.cs to cover the string path selection to a child contributed by [DayLightDancer](https://github.com/DayLightDancer)
# 1.5.34 (04 August 2023)
@@ -193,7 +202,6 @@
# 1.5.30 (28 June 2023)
- [#959](https://github.com/WireMock-Net/WireMock.Net/pull/959) - Fixed logic for FluentAssertions WithHeader [bug] contributed by [StefH](https://github.com/StefH)
- [#961](https://github.com/WireMock-Net/WireMock.Net/pull/961) - Add unit-test for Param MatcherModel LinqMatcher [test] contributed by [StefH](https://github.com/StefH)
- [#962](https://github.com/WireMock-Net/WireMock.Net/pull/962) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.Console.Net472.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#963](https://github.com/WireMock-Net/WireMock.Net/pull/963) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#958](https://github.com/WireMock-Net/WireMock.Net/issues/958) - [FluentAssertions] Should().HaveReceivedACall().WithHeader() only checks the first header with the matching key. [bug]
@@ -214,7 +222,6 @@
- [#945](https://github.com/WireMock-Net/WireMock.Net/issues/945) - Webhook logging [feature]
# 1.5.26 (25 May 2023)
- [#938](https://github.com/WireMock-Net/WireMock.Net/pull/938) - Add more unitests for CSharpFormatter utils [test] contributed by [StefH](https://github.com/StefH)
- [#939](https://github.com/WireMock-Net/WireMock.Net/pull/939) - WireMockMiddleware should use HandleRequestsSynchronously correctly [bug] contributed by [StefH](https://github.com/StefH)
- [#940](https://github.com/WireMock-Net/WireMock.Net/pull/940) - Code generator improvements contributed by [cezarypiatek](https://github.com/cezarypiatek)
- [#942](https://github.com/WireMock-Net/WireMock.Net/pull/942) - Add GetParameter method to IRequestMessage [feature] contributed by [StefH](https://github.com/StefH)
@@ -263,7 +270,6 @@
# 1.5.17 (25 February 2023)
- [#881](https://github.com/WireMock-Net/WireMock.Net/pull/881) - Add WithBodyAsJson builder method with accepts a Func [feature] contributed by [StefH](https://github.com/StefH)
- [#882](https://github.com/WireMock-Net/WireMock.Net/pull/882) - Add example code to test HTTP Status 400 and 500 [test] contributed by [StefH](https://github.com/StefH)
- [#890](https://github.com/WireMock-Net/WireMock.Net/pull/890) - AdminApiMappingBuilder [feature] contributed by [StefH](https://github.com/StefH)
# 1.5.16 (01 February 2023)
@@ -279,7 +285,6 @@
- [#871](https://github.com/WireMock-Net/WireMock.Net/pull/871) - Add UseWebhooksFireAndForget to Server ConvertMapping [bug] contributed by [ggradnig](https://github.com/ggradnig)
- [#872](https://github.com/WireMock-Net/WireMock.Net/pull/872) - Fix unsubscribe from LogEntriesChanged event handler [bug] contributed by [StefH](https://github.com/StefH)
- [#875](https://github.com/WireMock-Net/WireMock.Net/pull/875) - Fix Self referencing loop detected for property [bug] contributed by [eseneckiy](https://github.com/eseneckiy)
- [#877](https://github.com/WireMock-Net/WireMock.Net/pull/877) - Add unit test example for Transformer Handlebars String.Append String.Join [test] contributed by [StefH](https://github.com/StefH)
- [#701](https://github.com/WireMock-Net/WireMock.Net/issues/701) - Allow to create MappingModel from c# to be able to configure local and remote mocks similarly [feature]
- [#867](https://github.com/WireMock-Net/WireMock.Net/issues/867) - Can I build mappings with code and save them to JSON-file without starting server [feature]
- [#870](https://github.com/WireMock-Net/WireMock.Net/issues/870) - Can not unsubscribe from LogEntriesChanged event. [bug]
@@ -359,7 +364,6 @@
# 1.5.2 (24 July 2022)
- [#769](https://github.com/WireMock-Net/WireMock.Net/pull/769) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.3 to 2.1.7 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#770](https://github.com/WireMock-Net/WireMock.Net/pull/770) - Added some more tests for JsonMatcher + refactored some code to use nullable [test] contributed by [StefH](https://github.com/StefH)
- [#771](https://github.com/WireMock-Net/WireMock.Net/pull/771) - JsonPartialMatcher - support Regex [feature] contributed by [StefH](https://github.com/StefH)
# 1.5.1 (08 July 2022)
@@ -645,9 +649,6 @@
- [#492](https://github.com/WireMock-Net/WireMock.Net/pull/492) - Mark FluentMockServer, FluentMockServerSettings, BlacklistedHeaders and BlacklistedCookies as obsolete [feature] contributed by [StefH](https://github.com/StefH)
- [#489](https://github.com/WireMock-Net/WireMock.Net/issues/489) - Change &quot;blacklist&quot; and &quot;whitelist&quot; terms [feature]
# 1.2.15 (19 July 2020)
- [#485](https://github.com/WireMock-Net/WireMock.Net/pull/485) - Add fluent assertions for headers [test] contributed by [akamud](https://github.com/akamud)
# 1.2.14 (09 July 2020)
- [#479](https://github.com/WireMock-Net/WireMock.Net/pull/479) - An OpenApi (swagger) parser to generate MappingModel or mapping.json file [feature] contributed by [StefH](https://github.com/StefH)
- [#482](https://github.com/WireMock-Net/WireMock.Net/pull/482) - Add PartialMatch to logging / logentries [feature] contributed by [StefH](https://github.com/StefH)
@@ -948,7 +949,6 @@
# 1.0.4.21 (30 November 2018)
- [#221](https://github.com/WireMock-Net/WireMock.Net/pull/221) - Update dependencies [feature] contributed by [StefH](https://github.com/StefH)
- [#229](https://github.com/WireMock-Net/WireMock.Net/pull/229) - Fix proxy tests [test] contributed by [StefH](https://github.com/StefH)
- [#230](https://github.com/WireMock-Net/WireMock.Net/pull/230) - Add HandleBars Random functionality (#219) [feature] contributed by [StefH](https://github.com/StefH)
- [#231](https://github.com/WireMock-Net/WireMock.Net/pull/231) - Use RandomDataGenerator.Net 1.0.3.0 contributed by [StefH](https://github.com/StefH)
- [#232](https://github.com/WireMock-Net/WireMock.Net/pull/232) - Add SonarLint checks [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.6.3</VersionPrefix>
<VersionPrefix>1.6.5</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
@@ -44,12 +44,12 @@
</Choose>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" PrivateAssets="All" />
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.29.0.95321">
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -1,7 +1,7 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.6.3
SET version=1.6.5
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels test question invalid doc duplicate example environment --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%

View File

@@ -1,5 +1,6 @@
# 1.6.3 (07 September 2024)
- #1165 Fix listen on AnyIP for url 0.0.0.0
- #1154 Listen on all ips [bug]
# 1.6.5 (28 September 2024)
- #1175 Add WireMock.Net.AspNetCore.Middleware [feature]
- #1181 WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux [feature]
- #1182 pass in the request when no matching is found to the warn logger [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -41,13 +41,18 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
| - | - | - |
| &nbsp;&nbsp;**WireMock.Net** | [![NuGet Badge WireMock.Net](https://img.shields.io/nuget/v/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
| &nbsp;&nbsp;**WireMock.Net.StandAlone** | [![NuGet Badge WireMock.Net](https://img.shields.io/nuget/v/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.StandAlone?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
| &nbsp;&nbsp;**WireMock.Net.FluentAssertions** | [![NuGet Badge WireMock.Net.FluentAssertions](https://img.shields.io/nuget/v/WireMock.Net.FluentAssertions)](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [![MyGet Badge WireMock.Net.FluentAssertions](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.FluentAssertions?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
| &nbsp;&nbsp;**WireMock.Net.Matchers.CSharpCode** | [![NuGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/nuget/v/WireMock.Net.Matchers.CSharpCode)](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [![MyGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Matchers.CSharpCode?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
| &nbsp;&nbsp;**WireMock.Net.OpenApiParser** | [![NuGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/nuget/v/WireMock.Net.OpenApiParser)](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [![MyGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.OpenApiParser?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
| &nbsp;&nbsp;**WireMock.Net.RestClient** | [![NuGet Badge WireMock.Net.RestClient](https://img.shields.io/nuget/v/WireMock.Net.RestClient)](https://www.nuget.org/packages/WireMock.Net.RestClient) | [![MyGet Badge WireMock.Net.RestClient](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.RestClient?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
| &nbsp;&nbsp;**WireMock.Net.xUnit** | [![NuGet Badge WireMock.Net.xUnit](https://img.shields.io/nuget/v/WireMock.Net.xUnit)](https://www.nuget.org/packages/WireMock.Net.xUnit) | [![MyGet Badge WireMock.Net.xUnit](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.xUnit?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
| &nbsp;&nbsp;**WireMock.Net.Testcontainers** | [![NuGet Badge WireMock.Net.Testcontainers](https://img.shields.io/nuget/v/WireMock.Net.Testcontainers)](https://www.nuget.org/packages/WireMock.Net.Testcontainers) | [![MyGet Badge WireMock.Net.Testcontainers](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Testcontainers?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Testcontainers)
| &nbsp;&nbsp;**WireMock.Net.Aspire** | [![NuGet Badge WireMock.Net.Aspire](https://img.shields.io/nuget/v/WireMock.Net.Aspire)](https://www.nuget.org/packages/WireMock.Net.Aspire) | [![MyGet Badge WireMock.Net.Aspire](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Aspire?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Aspire)
| &nbsp;&nbsp;**WireMock.Net.AspNetCore.Middleware** | [![NuGet Badge WireMock.Net.AspNetCore.Middleware](https://img.shields.io/nuget/v/WireMock.Net.AspNetCore.Middleware)](https://www.nuget.org/packages/WireMock.Net.AspNetCore.Middleware) | [![MyGet Badge WireMock.Net.AspNetCore.Middleware](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.AspNetCore.Middleware?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.AspNetCore.Middleware)
| | | |
| &nbsp;&nbsp;**WireMock.Net.FluentAssertions** | [![NuGet Badge WireMock.Net.FluentAssertions](https://img.shields.io/nuget/v/WireMock.Net.FluentAssertions)](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [![MyGet Badge WireMock.Net.FluentAssertions](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.FluentAssertions?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
| &nbsp;&nbsp;**WireMock.Net.xUnit** | [![NuGet Badge WireMock.Net.xUnit](https://img.shields.io/nuget/v/WireMock.Net.xUnit)](https://www.nuget.org/packages/WireMock.Net.xUnit) | [![MyGet Badge WireMock.Net.xUnit](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.xUnit?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
| &nbsp;&nbsp;**WireMock.Net.TUnit** | [![NuGet Badge WireMock.Net.TUnit](https://img.shields.io/nuget/v/WireMock.Net.TUnit)](https://www.nuget.org/packages/WireMock.Net.TUnit) | [![MyGet Badge WireMock.Net.TUnit](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.TUnit?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.TUnit)
| | | |
| &nbsp;&nbsp;**WireMock.Net.Matchers.CSharpCode** | [![NuGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/nuget/v/WireMock.Net.Matchers.CSharpCode)](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [![MyGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Matchers.CSharpCode?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
| &nbsp;&nbsp;**WireMock.Net.OpenApiParser** | [![NuGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/nuget/v/WireMock.Net.OpenApiParser)](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [![MyGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.OpenApiParser?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
| | | |
| &nbsp;&nbsp;**WireMock.Net.RestClient** | [![NuGet Badge WireMock.Net.RestClient](https://img.shields.io/nuget/v/WireMock.Net.RestClient)](https://www.nuget.org/packages/WireMock.Net.RestClient) | [![MyGet Badge WireMock.Net.RestClient](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.RestClient?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
| &nbsp;&nbsp;**WireMock.Org.RestClient** | [![NuGet Badge WireMock.Org.RestClient](https://img.shields.io/nuget/v/WireMock.Org.RestClient)](https://www.nuget.org/packages/WireMock.Org.RestClient) | [![MyGet Badge WireMock.Org.RestClient](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Org.RestClient?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)

View File

@@ -131,6 +131,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Aspire.TestApp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspireApp1.AppHostOriginal", "examples-Aspire\AspireApp1.AppHostOriginal\AspireApp1.AppHostOriginal.csproj", "{C9210DA3-F390-4598-8512-349A473FE9C9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnit", "src\WireMock.Net.TUnit\WireMock.Net.TUnit.csproj", "{91024A93-848F-4A02-AF53-5EBE5834E23C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnitTests", "test\WireMock.Net.TUnitTests\WireMock.Net.TUnitTests.csproj", "{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.WebApplication", "examples\WireMock.Net.WebApplication\WireMock.Net.WebApplication.csproj", "{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.AspNetCore.Middleware", "src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A13}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TestWebApplication", "test\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj", "{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Middleware.Tests", "test\WireMock.Net.Middleware.Tests\WireMock.Net.Middleware.Tests.csproj", "{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -317,6 +329,30 @@ Global
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.Build.0 = Release|Any CPU
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.Build.0 = Release|Any CPU
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.Build.0 = Release|Any CPU
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.Build.0 = Release|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.Build.0 = Release|Any CPU
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.Build.0 = Release|Any CPU
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -369,6 +405,12 @@ Global
{CE602F57-FEF8-4559-A9E0-6200BE1BF398} = {0BB8B634-407A-4610-A91F-11586990767A}
{F1B5999D-D22E-48A6-AB86-18A7876BD32E} = {0BB8B634-407A-4610-A91F-11586990767A}
{C9210DA3-F390-4598-8512-349A473FE9C9} = {AD474543-0715-49F2-A284-936B060BF736}
{91024A93-848F-4A02-AF53-5EBE5834E23C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE} = {0BB8B634-407A-4610-A91F-11586990767A}
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{B6269AAC-170A-4346-8B9A-579DED3D9A13} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE} = {0BB8B634-407A-4610-A91F-11586990767A}
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5} = {0BB8B634-407A-4610-A91F-11586990767A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}

View File

@@ -38,7 +38,7 @@ jobs:
# See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage
- script: |
dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true
dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true
displayName: 'Begin analysis on SonarCloud'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
@@ -52,13 +52,15 @@ jobs:
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-1.xml"
displayName: 'Execute WireMock.Net.Tests with Coverage'
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml"
dotnet-coverage collect "dotnet test ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-tunit.xml"
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-middleware.xml"
displayName: 'Execute WireMock.Net.Tests with Coverage'
- task: CmdLine@2
inputs:
script: |
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-2.xml"
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml"
displayName: 'Execute WireMock.Net.Aspire.Tests with Coverage'
- task: CmdLine@2

View File

@@ -1,7 +1,7 @@
// Copyright © WireMock.Net
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using Testcontainers.MsSql;
using WireMock.Net.Testcontainers;
namespace WireMock.Net.TestcontainersExample;
@@ -10,17 +10,134 @@ internal class Program
{
private static async Task Main(string[] args)
{
var container = new WireMockContainerBuilder()
var original = Console.ForegroundColor;
try
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Linux");
await TestAsync("sheyenrath/wiremock.net:1.6.4");
await Task.Delay(1_000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ForegroundColor = original;
}
try
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Linux Alpine");
await TestAsync("sheyenrath/wiremock.net-alpine:1.6.4");
await Task.Delay(1_000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ForegroundColor = original;
}
try
{
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("WithLinux");
await TestAsync("WithLinux");
await Task.Delay(1_000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ForegroundColor = original;
}
try
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Windows");
await TestAsync("sheyenrath/wiremock.net-windows:1.6.4");
await Task.Delay(1_000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ForegroundColor = original;
}
try
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("WithWindows");
await TestAsync("WithWindows");
await Task.Delay(1_000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ForegroundColor = original;
}
try
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Automatic");
await TestAsync();
}
finally
{
Console.ForegroundColor = original;
}
}
private static async Task TestAsync(string? image = null)
{
var builder = new WireMockContainerBuilder()
.WithAdminUserNameAndPassword("x", "y")
.WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings")
.WithWatchStaticMappings(true)
.WithAutoRemove(true)
.WithCleanUp(true)
.Build();
.WithCleanUp(true);
await container.StartAsync().ConfigureAwait(false);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
builder = builder.WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings");
}
else
{
builder = builder.WithMappings("./examples/WireMock.Net.Console.NET6/__admin/mappings");
}
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1)).ConfigureAwait(false);
if (image != null)
{
builder = image switch
{
"WithWindows" => builder.WithWindowsImage(),
"WithLinux" => builder.WithLinuxImage(),
_ => builder.WithImage(image)
};
}
var container = builder.Build();
await container.StartAsync();
await Task.Delay(1_000);
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1));
Console.WriteLine("logs = " + logs.Stdout);
var restEaseApiClient = container.CreateWireMockAdminClient();
@@ -36,10 +153,5 @@ internal class Program
Console.WriteLine("result = " + result);
await container.StopAsync();
var sql = new MsSqlBuilder()
.WithAutoRemove(true)
.WithCleanUp(true)
.Build();
}
}

View File

@@ -1,24 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Testcontainers.MsSql" Version="3.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,56 @@
using WireMock.Net.AspNetCore.Middleware;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
var builder = WebApplication.CreateBuilder(args);
if (!builder.Environment.IsProduction())
{
builder.Services.AddWireMockService(server =>
{
server.Given(Request.Create()
.WithPath("/test1")
.UsingAnyMethod()
).RespondWith(Response.Create()
.WithBody("1 : WireMock.Net !")
);
server.Given(Request.Create()
.WithPath("/test2")
.UsingAnyMethod()
).RespondWith(Response.Create()
.WithBody("2 : WireMock.Net !")
);
}, true);
}
var app = builder.Build();
app.MapGet("/weatherforecast", async (HttpClient client) =>
{
var result = await client.GetStringAsync("https://real-api:12345/test1");
return Enumerable.Range(1, 3).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
result
));
});
app.MapGet("/weatherforecast2", async (IHttpClientFactory factory) =>
{
using var client = factory.CreateClient();
var result = await client.GetStringAsync("https://real-api:12345/test2");
return Enumerable.Range(1, 3).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
result
));
});
await app.RunAsync();

View File

@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:57375",
"sslPort": 44333
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5112",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:7021;http://localhost:5112",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,4 @@
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,25 @@
// Copyright © WireMock.Net
using WireMock.Types;
// ReSharper disable once CheckNamespace
namespace WireMock.Util;
// ReSharper disable once InconsistentNaming
public static class IBodyDataExtensions
{
public static BodyType GetBodyType(this IBodyData bodyData)
{
if (bodyData.DetectedBodyTypeFromContentType is not null and not BodyType.None)
{
return bodyData.DetectedBodyTypeFromContentType.Value;
}
if (bodyData.DetectedBodyType is not null and not BodyType.None)
{
return bodyData.DetectedBodyType.Value;
}
return BodyType.None;
}
}

View File

@@ -0,0 +1,9 @@
// Copyright © WireMock.Net
namespace WireMock.Net.AspNetCore.Middleware;
internal static class AppConstants
{
internal const string HEADER_REDIRECT = "X-WireMock-Redirect";
internal const string HEADER_RESPONSE_DELAY = "X-WireMock-Response-Delay";
}

View File

@@ -0,0 +1,72 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Stef.Validation;
using WireMock.Server;
namespace WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
/// <summary>
/// DelegatingHandler that takes requests made via the <see cref="HttpClient"/>
/// and routes them to the <see cref="WireMockServer"/>.
/// </summary>
internal class WireMockDelegationHandler : DelegatingHandler
{
private readonly ILogger<WireMockDelegationHandler> _logger;
private readonly WireMockServerInstance _server;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly WireMockDelegationHandlerSettings _settings;
/// <summary>
/// Creates a new instance of <see cref="WireMockDelegationHandler"/>
/// </summary>
public WireMockDelegationHandler(
ILogger<WireMockDelegationHandler> logger,
WireMockServerInstance server,
IHttpContextAccessor httpContextAccessor,
WireMockDelegationHandlerSettings settings
)
{
_server = Guard.NotNull(server);
_httpContextAccessor = Guard.NotNull(httpContextAccessor);
_logger = Guard.NotNull(logger);
_settings = Guard.NotNull(settings);
}
/// <inheritdoc />
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Guard.NotNull(request);
Guard.NotNull(_httpContextAccessor.HttpContext);
if (_settings.AlwaysRedirect || IsWireMockRedirectHeaderSetToTrue())
{
_logger.LogDebug("Redirecting request to WireMock server");
if (_server.Instance?.Url != null)
{
request.RequestUri = new Uri(_server.Instance.Url + request.RequestUri!.PathAndQuery);
}
}
if (TryGetDelayHeaderValue(out var delayInMs))
{
await Task.Delay(delayInMs, cancellationToken);
}
return await base.SendAsync(request, cancellationToken);
}
private bool IsWireMockRedirectHeaderSetToTrue()
{
return
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_REDIRECT, out var values) &&
bool.TryParse(values.ToString(), out var shouldRedirectToWireMock) && shouldRedirectToWireMock;
}
private bool TryGetDelayHeaderValue(out int delayInMs)
{
delayInMs = 0;
return
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_RESPONSE_DELAY, out var values) &&
int.TryParse(values.ToString(), out delayInMs);
}
}

View File

@@ -0,0 +1,8 @@
// Copyright © WireMock.Net
namespace WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
internal class WireMockDelegationHandlerSettings
{
public bool AlwaysRedirect { get; set; }
}

View File

@@ -0,0 +1,52 @@
// Copyright © WireMock.Net
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http;
using Stef.Validation;
using WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.AspNetCore.Middleware;
/// <summary>
/// Extension methods for <see cref="IServiceCollection"/>.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds all the components necessary to run WireMock.Net as a background service.
/// </summary>
public static IServiceCollection AddWireMockService(
this IServiceCollection services,
Action<WireMockServer> configure,
bool alwaysRedirectToWireMock = true,
WireMockServerSettings? settings = null
)
{
Guard.NotNull(services);
Guard.NotNull(configure);
services.AddTransient<WireMockDelegationHandler>();
services.AddSingleton(new WireMockServerInstance(configure, settings));
services.AddSingleton(new WireMockDelegationHandlerSettings
{
AlwaysRedirect = alwaysRedirectToWireMock
});
services.AddHostedService<WireMockBackgroundService>();
services.AddHttpClient();
services.AddHttpContextAccessor();
services.ConfigureAll<HttpClientFactoryOptions>(options =>
{
options.HttpMessageHandlerBuilderActions.Add(builder =>
{
builder.AdditionalHandlers.Add(builder.Services.GetRequiredService<WireMockDelegationHandler>());
});
});
return services;
}
}

View File

@@ -0,0 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Description>Middleware which can be used to host WireMock.Net as a Middleware background process in a AspNetCore WebApplication</Description>
<AssemblyTitle>WireMock.Net.AspNetCore.Middleware</AssemblyTitle>
<Authors>Matthew Yost;Stef Heyenrath</Authors>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net.AspNetCore.Middleware</AssemblyName>
<PackageId>WireMock.Net.AspNetCore.Middleware</PackageId>
<PackageTags>dotnet;middleware;wiremock;service;webapplication;aspnetcore</PackageTags>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A13}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>WireMock.Net-LogoAspire.png</PackageIcon>
<ApplicationIcon>../../resources/WireMock.Net-LogoAspire.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<None Remove="../../resources/WireMock.Net-Logo.png" />
<None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,39 @@
// Copyright © WireMock.Net
using Microsoft.Extensions.Hosting;
using Stef.Validation;
using WireMock.Server;
namespace WireMock.Net.AspNetCore.Middleware;
/// <summary>
/// A <see cref="BackgroundService"/> used to start/stop the <see cref="WireMockServer"/>
/// </summary>
internal class WireMockBackgroundService : BackgroundService
{
private readonly WireMockServerInstance _serverInstance;
/// <summary>
/// Creates a new <see cref="BackgroundService"/> using an instance
/// of <see cref="WireMockServerInstance"/>
/// </summary>
/// <param name="serverInstance"></param>
public WireMockBackgroundService(WireMockServerInstance serverInstance)
{
_serverInstance = Guard.NotNull(serverInstance);
}
/// <inheritdoc />
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_serverInstance.Start();
return Task.CompletedTask;
}
/// <inheritdoc />
public override Task StopAsync(CancellationToken cancellationToken)
{
_serverInstance.Stop();
return base.StopAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,49 @@
// Copyright © WireMock.Net
using Stef.Validation;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.AspNetCore.Middleware;
/// <summary>
/// WireMockServer Instance object
/// </summary>
internal class WireMockServerInstance
{
private readonly Action<WireMockServer> _configureAction;
private readonly WireMockServerSettings? _settings;
/// <summary>
/// Creates a new instance and provides ability to add configuration
/// for the start method of <see cref="WireMockServer"/>
/// </summary>
public WireMockServerInstance(Action<WireMockServer> configure, WireMockServerSettings? settings = null)
{
_configureAction = Guard.NotNull(configure);
_settings = settings;
}
/// <summary>
/// Instance accessor for the <see cref="WireMockServer" />
/// </summary>
public WireMockServer? Instance { get; private set; }
/// <summary>
/// Configures and starts <see cref="WireMockServer"/> instance for use.
/// </summary>
public void Start()
{
Instance = _settings != null ? WireMockServer.Start(_settings) : WireMockServer.Start();
_configureAction.Invoke(Instance);
}
/// <summary>
/// Stops the <see cref="WireMockServer"/>
/// </summary>
public void Stop()
{
Instance?.Stop();
}
}

View File

@@ -43,7 +43,7 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<PackageReference Include="CS-Script" Version="4.8.13" />
<PackageReference Include="CS-Script" Version="4.8.17" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,80 @@
// Copyright © WireMock.Net
using System;
using Newtonsoft.Json;
using Stef.Validation;
using TUnit.Core.Logging;
using WireMock.Admin.Requests;
using WireMock.Logging;
namespace WireMock.Net.TUnit;
/// <summary>
/// When using TUnit, this class enables to log the output from WireMock.Net to the <see cref="TUnitLogger"/>.
/// </summary>
// ReSharper disable once InconsistentNaming
public sealed class TUnitWireMockLogger : IWireMockLogger
{
private readonly TUnitLogger _tUnitLogger;
/// <summary>
/// Create a new instance on the <see cref="TUnitWireMockLogger"/>.
/// </summary>
/// <param name="tUnitLogger">Represents a class which can be used to provide test output.</param>
public TUnitWireMockLogger(TUnitLogger tUnitLogger)
{
_tUnitLogger = Guard.NotNull(tUnitLogger);
}
/// <inheritdoc />
public void Debug(string formatString, params object[] args)
{
_tUnitLogger.LogDebug(Format("Debug", formatString, args));
}
/// <inheritdoc />
public void Info(string formatString, params object[] args)
{
_tUnitLogger.LogInformation(Format("Info", formatString, args));
}
/// <inheritdoc />
public void Warn(string formatString, params object[] args)
{
_tUnitLogger.LogWarning(Format("Warning", formatString, args));
}
/// <inheritdoc />
public void Error(string formatString, params object[] args)
{
_tUnitLogger.LogError(Format("Error", formatString, args));
}
/// <inheritdoc />
public void Error(string formatString, Exception exception)
{
_tUnitLogger.LogError(Format("Error", formatString, exception.Message), exception);
if (exception is AggregateException ae)
{
ae.Handle(ex =>
{
_tUnitLogger.LogError(Format("Error", "Exception {0}", ex.Message), exception);
return true;
});
}
}
/// <inheritdoc />
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{
var message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
_tUnitLogger.LogDebug(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
}
private static string Format(string level, string formatString, params object[] args)
{
var message = args.Length > 0 ? string.Format(formatString, args) : formatString;
return $"{DateTime.UtcNow} [{level}] : {message}";
}
}

View File

@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Some extensions for TUnit (TUnitLogger)</Description>
<AssemblyTitle>WireMock.Net.TUnit</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net.TUnit</AssemblyName>
<RootNamespace>WireMock.Net.Tunit</RootNamespace>
<PackageId>WireMock.Net.TUnit</PackageId>
<PackageTags>tdd;wiremock;test;unittest;TUnit</PackageTags>
<ProjectGuid>{0DE0954F-8C00-4E8D-B94A-4361FC1CB34A}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Stef.Validation" Version="0.1.1" />
<PackageReference Include="TUnit.Core" Version="0.1.817" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -28,7 +28,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Stef.Validation" Version="0.1.1" />
<PackageReference Include="Testcontainers" Version="[3.9.0]" />
<PackageReference Include="Testcontainers" Version="3.10.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Builders;
@@ -17,15 +18,14 @@ namespace WireMock.Net.Testcontainers;
/// </summary>
public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContainerBuilder, WireMockContainer, WireMockConfiguration>
{
private readonly Dictionary<bool, ContainerInfo> _info = new()
private const string DefaultLogger = "WireMockConsoleLogger";
private readonly Dictionary<OSPlatform, ContainerInfo> _info = new()
{
{ false, new ContainerInfo("sheyenrath/wiremock.net:latest", "/app/__admin/mappings") },
{ true, new ContainerInfo("sheyenrath/wiremock.net-windows:latest", @"c:\app\__admin\mappings") }
{ OSPlatform.Linux, new ContainerInfo("sheyenrath/wiremock.net-alpine", "/app/__admin/mappings") },
{ OSPlatform.Windows, new ContainerInfo("sheyenrath/wiremock.net-windows", @"c:\app\__admin\mappings") }
};
private const string DefaultLogger = "WireMockConsoleLogger";
private readonly Lazy<Task<bool>> _isWindowsAsLazy = new(async () =>
private readonly Lazy<Task<OSPlatform>> _getOSAsLazy = new(async () =>
{
if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null)
{
@@ -36,9 +36,12 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
using var dockerClient = dockerClientConfig.CreateClient();
var version = await dockerClient.System.GetVersionAsync();
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) > -1;
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
});
private OSPlatform? _imageOS;
private string? _staticMappingsPath;
/// <summary>
/// Initializes a new instance of the <see cref="ContainerBuilder" /> class.
/// </summary>
@@ -48,14 +51,36 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
}
/// <summary>
/// Automatically set the correct image (Linux or Windows) for WireMock which to create the container.
/// Automatically use the correct image for WireMock.
/// For Linux this is "sheyenrath/wiremock.net-alpine:latest"
/// For Windows this is "sheyenrath/wiremock.net-windows:latest"
/// </summary>
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
[PublicAPI]
public WireMockContainerBuilder WithImage()
{
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
return WithImage(_info[isWindows].Image);
_imageOS ??= _getOSAsLazy.Value.GetAwaiter().GetResult();
return WithImage(_imageOS.Value);
}
/// <summary>
/// Automatically use a Linux image for WireMock. This is "sheyenrath/wiremock.net-alpine:latest"
/// </summary>
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
[PublicAPI]
public WireMockContainerBuilder WithLinuxImage()
{
return WithImage(OSPlatform.Linux);
}
/// <summary>
/// Automatically use a Windows image for WireMock. This is "sheyenrath/wiremock.net-windows:latest"
/// </summary>
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
[PublicAPI]
public WireMockContainerBuilder WithWindowsImage()
{
return WithImage(OSPlatform.Windows);
}
/// <summary>
@@ -118,13 +143,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
[PublicAPI]
public WireMockContainerBuilder WithMappings(string path, bool includeSubDirectories = false)
{
Guard.NotNullOrEmpty(path);
_staticMappingsPath = Guard.NotNullOrEmpty(path);
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
return WithReadStaticMappings()
.WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}")
.WithBindMount(path, _info[isWindows].MappingsPath);
return WithReadStaticMappings().WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}");
}
private WireMockContainerBuilder(WireMockConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration)
@@ -138,9 +159,33 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
/// <inheritdoc />
public override WireMockContainer Build()
{
Validate();
var builder = this;
return new WireMockContainer(DockerResourceConfiguration);
// In case no image has been set, set the image using internal logic.
if (DockerResourceConfiguration.Image == null)
{
builder = WithImage();
}
// In case the _imageOS is not set, determine it from the Image FullName.
if (_imageOS == null)
{
if (builder.DockerResourceConfiguration.Image.FullName.IndexOf("wiremock.net", StringComparison.OrdinalIgnoreCase) < 0)
{
throw new InvalidOperationException();
}
_imageOS = builder.DockerResourceConfiguration.Image.FullName.IndexOf("windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
}
if (!string.IsNullOrEmpty(_staticMappingsPath))
{
builder = builder.WithBindMount(_staticMappingsPath, _info[_imageOS.Value].MappingsPath);
}
builder.Validate();
return new WireMockContainer(builder.DockerResourceConfiguration);
}
/// <inheritdoc />
@@ -148,14 +193,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
{
var builder = base.Init();
// In case no image has been set, set the image using internal logic.
if (builder.DockerResourceConfiguration.Image == null)
{
builder = builder.WithImage();
}
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
var waitForContainerOS = isWindows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
return builder
.WithPortBinding(WireMockContainer.ContainerPort, true)
.WithCommand($"--WireMockLogger {DefaultLogger}")
@@ -179,4 +217,10 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
{
return new WireMockContainerBuilder(new WireMockConfiguration(oldValue, newValue));
}
private WireMockContainerBuilder WithImage(OSPlatform os)
{
_imageOS = os;
return WithImage(_info[os].Image);
}
}

View File

@@ -73,8 +73,6 @@ public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
private static string Format(string level, string formatString, params object[] args)
{
Guard.NotNull(formatString);
var message = args.Length > 0 ? string.Format(formatString, args) : formatString;
return $"{DateTime.UtcNow} [{level}] : {message}";
}

View File

@@ -9,6 +9,7 @@ using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Constants;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Http;
@@ -33,12 +34,14 @@ internal static class HttpRequestMessageHelper
MediaTypeHeaderValue.TryParse(value, out contentType);
}
httpRequestMessage.Content = requestMessage.BodyData?.DetectedBodyType switch
var bodyData = requestMessage.BodyData;
httpRequestMessage.Content = bodyData?.GetBodyType() switch
{
BodyType.Bytes => ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType),
BodyType.Json => StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType),
BodyType.String => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
BodyType.FormUrlEncoded => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
BodyType.Bytes => ByteArrayContentHelper.Create(bodyData!.BodyAsBytes!, contentType),
BodyType.Json => StringContentHelper.Create(JsonConvert.SerializeObject(bodyData!.BodyAsJson), contentType),
BodyType.String => StringContentHelper.Create(bodyData!.BodyAsString!, contentType),
BodyType.FormUrlEncoded => StringContentHelper.Create(bodyData!.BodyAsString!, contentType),
_ => httpRequestMessage.Content
};

View File

@@ -136,30 +136,37 @@ namespace WireMock.Owin.Mappers
return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
}
private async Task<byte[]?> GetNormalBodyAsync(IResponseMessage responseMessage)
{
switch (responseMessage.BodyData?.DetectedBodyType)
private async Task<byte[]?> GetNormalBodyAsync(IResponseMessage responseMessage) {
var bodyData = responseMessage.BodyData;
switch (bodyData?.GetBodyType())
{
case BodyType.String:
case BodyType.FormUrlEncoded:
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
return (bodyData.Encoding ?? _utf8NoBom).GetBytes(bodyData.BodyAsString!);
case BodyType.Json:
var formatting = responseMessage.BodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None;
var jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
var formatting = bodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None;
var jsonBody = JsonConvert.SerializeObject(bodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
return (bodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
#if PROTOBUF
case BodyType.ProtoBuf:
var protoDefinition = responseMessage.BodyData.ProtoDefinition?.Invoke().Text;
return await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinition, responseMessage.BodyData.ProtoBufMessageType, responseMessage.BodyData.BodyAsJson).ConfigureAwait(false);
var protoDefinition = bodyData.ProtoDefinition?.Invoke().Text;
return await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinition, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false);
#endif
case BodyType.Bytes:
return responseMessage.BodyData.BodyAsBytes;
return bodyData.BodyAsBytes;
case BodyType.File:
return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile!);
return _options.FileSystemHandler?.ReadResponseBodyAsFile(bodyData.BodyAsFile!);
case BodyType.MultiPart:
_options.Logger.Warn("MultiPart body type is not handled!");
break;
case BodyType.None:
break;
}
return null;
@@ -171,10 +178,7 @@ namespace WireMock.Owin.Mappers
AppendResponseHeader(
response,
HttpKnownHeaderNames.Date,
new[]
{
DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture)
}
[ DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture) ]
);
// Set other headers

View File

@@ -126,7 +126,7 @@ namespace WireMock.Owin
if (targetMapping == null)
{
logRequest = true;
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found", ctx.Request);
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
return;
}
@@ -357,4 +357,4 @@ namespace WireMock.Owin
}
}
}
}
}

View File

@@ -623,7 +623,7 @@ public partial class WireMockServer
{
var requestModel = DeserializeObject<RequestModel>(requestMessage);
var request = (Request)InitRequestBuilder(requestModel, false)!;
var request = (Request)InitRequestBuilder(requestModel);
var dict = new Dictionary<ILogEntry, RequestMatchResult>();
foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/")))

View File

@@ -36,17 +36,13 @@ public partial class WireMockServer
}
}
private Guid? ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string? path = null)
private Guid ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string? path = null)
{
Guard.NotNull(mappingModel);
Guard.NotNull(mappingModel.Request);
Guard.NotNull(mappingModel.Response);
var requestBuilder = InitRequestBuilder(mappingModel.Request, true);
if (requestBuilder == null)
{
return null;
}
var requestBuilder = InitRequestBuilder(mappingModel.Request);
var respondProvider = Given(requestBuilder, mappingModel.SaveToFile == true);
@@ -126,9 +122,9 @@ public partial class WireMockServer
return respondProvider.Guid;
}
private IRequestBuilder? InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
private IRequestBuilder InitRequestBuilder(RequestModel requestModel)
{
IRequestBuilder requestBuilder = Request.Create();
var requestBuilder = Request.Create();
if (requestModel.ClientIP != null)
{
@@ -146,13 +142,11 @@ public partial class WireMockServer
}
}
bool pathOrUrlMatchersValid = false;
if (requestModel.Path != null)
{
if (requestModel.Path is string path)
{
requestBuilder = requestBuilder.WithPath(path);
pathOrUrlMatchersValid = true;
}
else
{
@@ -161,7 +155,6 @@ public partial class WireMockServer
{
var matchOperator = StringUtils.ParseMatchOperator(pathModel.MatchOperator);
requestBuilder = requestBuilder.WithPath(matchOperator, pathModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
pathOrUrlMatchersValid = true;
}
}
}
@@ -170,7 +163,6 @@ public partial class WireMockServer
if (requestModel.Url is string url)
{
requestBuilder = requestBuilder.WithUrl(url);
pathOrUrlMatchersValid = true;
}
else
{
@@ -179,17 +171,10 @@ public partial class WireMockServer
{
var matchOperator = StringUtils.ParseMatchOperator(urlModel.MatchOperator);
requestBuilder = requestBuilder.WithUrl(matchOperator, urlModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
pathOrUrlMatchersValid = true;
}
}
}
if (pathOrUrlRequired && !pathOrUrlMatchersValid)
{
_settings.Logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
return null;
}
if (requestModel.Methods != null)
{
var matchBehaviour = requestModel.MethodsRejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
@@ -233,7 +218,7 @@ public partial class WireMockServer
{
foreach (var paramModel in requestModel.Params.Where(p => p is { Matchers: { } }))
{
bool ignoreCase = paramModel.IgnoreCase == true;
var ignoreCase = paramModel.IgnoreCase == true;
requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers!.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
}
}
@@ -253,7 +238,7 @@ public partial class WireMockServer
private static IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
{
IResponseBuilder responseBuilder = Response.Create();
var responseBuilder = Response.Create();
if (responseModel.Delay > 0)
{

View File

@@ -8,10 +8,7 @@ namespace WireMock.Net.Aspire.Tests;
[ExcludeFromCodeCoverage]
internal static class DockerUtils
{
public static bool IsDockerRunningLinuxContainerMode()
{
return IsDockerRunning() && IsLinuxContainerMode();
}
public static Lazy<bool> IsDockerRunningLinuxContainerMode => new(() => IsDockerRunning() && IsLinuxContainerMode());
private static bool IsDockerRunning()
{

View File

@@ -0,0 +1,16 @@
// Copyright © WireMock.Net
namespace WireMock.Net.Aspire.Tests.Facts;
public sealed class DockerIsRunningInLinuxContainerModeFact : FactAttribute
{
private const string SkipReason = "Docker is not running in Linux container mode. Skipping test.";
public DockerIsRunningInLinuxContainerModeFact()
{
if (!DockerUtils.IsDockerRunningLinuxContainerMode.Value)
{
Skip = SkipReason;
}
}
}

View File

@@ -3,6 +3,7 @@
using System.Net.Http.Json;
using FluentAssertions;
using Projects;
using WireMock.Net.Aspire.Tests.Facts;
using Xunit.Abstractions;
namespace WireMock.Net.Aspire.Tests;
@@ -11,15 +12,9 @@ public class IntegrationTests(ITestOutputHelper output)
{
private record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary);
[Fact]
[DockerIsRunningInLinuxContainerModeFact]
public async Task StartAppHostWithWireMockAndCreateHttpClientToCallTheMockedWeatherForecastEndpoint()
{
if (!DockerUtils.IsDockerRunningLinuxContainerMode())
{
output.WriteLine("Docker is not running in Linux container mode. Skipping test.");
return;
}
// Arrange
var appHostBuilder = await DistributedApplicationTestingBuilder.CreateAsync<WireMock_Net_Aspire_TestAppHost>();
await using var app = await appHostBuilder.BuildAsync();
@@ -44,15 +39,9 @@ public class IntegrationTests(ITestOutputHelper output)
weatherForecasts2.Should().HaveCount(5);
}
[Fact]
[DockerIsRunningInLinuxContainerModeFact]
public async Task StartAppHostWithWireMockAndCreateWireMockAdminClientToCallTheAdminEndpoint()
{
if (!DockerUtils.IsDockerRunningLinuxContainerMode())
{
output.WriteLine("Docker is not running in Linux container mode. Skipping test.");
return;
}
// Arrange
var appHostBuilder = await DistributedApplicationTestingBuilder.CreateAsync<WireMock_Net_Aspire_TestAppHost>();
await using var app = await appHostBuilder.BuildAsync();

View File

@@ -6,6 +6,7 @@
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<SonarQubeExclude>true</SonarQubeExclude>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>

View File

@@ -0,0 +1,25 @@
// Copyright © WireMock.Net
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
namespace WireMock.Net.Middleware.Tests;
internal class CustomWebApplicationFactory<TEntryPoint> : WebApplicationFactory<TEntryPoint>
where TEntryPoint : class
{
private readonly List<(string Key, string Value)> _settings = new();
public CustomWebApplicationFactory(bool alwaysRedirectToWireMock = true)
{
_settings.Add(("AlwaysRedirectToWireMock", alwaysRedirectToWireMock.ToString().ToLowerInvariant()));
}
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
foreach (var arg in _settings)
{
builder.UseSetting(arg.Key, arg.Value);
}
}
}

View File

@@ -0,0 +1,49 @@
// Copyright © WireMock.Net
using FluentAssertions;
using WireMock.Net.TestWebApplication;
namespace WireMock.Net.Middleware.Tests;
public class IntegrationTests
{
[Theory]
[InlineData("/real1", "Hello 1 from WireMock.Net !")]
[InlineData("/real2", "Hello 2 from WireMock.Net !")]
public async Task CallingRealApi_WithAlwaysRedirectToWireMockIsTrue(string requestUri, string expectedResponse)
{
// Arrange
await using var factory = new CustomWebApplicationFactory<Program>();
using var client = factory.CreateClient();
// Act
var response = await client.GetAsync(requestUri);
// Assert
response.EnsureSuccessStatusCode();
var stringResponse = await response.Content.ReadAsStringAsync();
stringResponse.Should().Be(expectedResponse);
}
[Theory]
[InlineData("/real1", "Hello 1 from WireMock.Net !")]
[InlineData("/real2", "Hello 2 from WireMock.Net !")]
public async Task CallingRealApi_WithAlwaysRedirectToWireMockIsFalse(string requestUri, string expectedResponse)
{
// Arrange
await using var factory = new CustomWebApplicationFactory<Program>(false);
using var client = factory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Add("X-WireMock-Redirect", "true");
request.Headers.Add("X-WireMock-Response-Delay", "10");
// Act
var response = await client.SendAsync(request);
// Assert
response.EnsureSuccessStatusCode();
var stringResponse = await response.Content.ReadAsStringAsync();
stringResponse.Should().Be(expectedResponse);
}
}

View File

@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Codecov" Version="1.13.0" />
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,37 @@
// Copyright © WireMock.Net
using WireMock.Net.TUnit;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.TUnitTests;
// ReSharper disable once InconsistentNaming
public class TUnitTests
{
[Test]
public async Task Test_TUnitWireMockLogger()
{
// Assign
var path = $"/foo_{Guid.NewGuid()}";
using var server = WireMockServer.Start(new WireMockServerSettings
{
Logger = new TUnitWireMockLogger(TestContext.Current!.GetDefaultLogger())
});
server
.Given(Request.Create()
.WithPath(path)
.UsingGet())
.RespondWith(Response.Create().WithBody("TUnit"));
// Act
var response = await server.CreateClient().GetStringAsync($"{server.Url}{path}");
// Assert
await Assert.That(response).IsEqualTo("TUnit");
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsTestProject>true</IsTestProject>
<SonarQubeExclude>true</SonarQubeExclude>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TUnit" Version="0.1.817" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.TUnit\WireMock.Net.TUnit.csproj" />
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,49 @@
using WireMock.Net.AspNetCore.Middleware;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
namespace WireMock.Net.TestWebApplication;
// Make the implicit Program class public so test projects can access it.
public class Program
{
public static async Task Main(string[] args)
{
var alwaysRedirectToWireMock = args.Contains("--AlwaysRedirectToWireMock=true");
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddWireMockService(server =>
{
server.Given(Request.Create()
.WithPath("/test1")
.UsingAnyMethod()
).RespondWith(Response.Create()
.WithBody("Hello 1 from WireMock.Net !")
);
server.Given(Request.Create()
.WithPath("/test2")
.UsingAnyMethod()
).RespondWith(Response.Create()
.WithBody("Hello 2 from WireMock.Net !")
);
}, alwaysRedirectToWireMock);
var app = builder.Build();
app.MapGet("/real1", async (HttpClient client) =>
{
var result = await client.GetStringAsync("https://real-api:12345/test1");
return result;
});
app.MapGet("/real2", async (IHttpClientFactory factory) =>
{
using var client = factory.CreateClient();
return await client.GetStringAsync("https://real-api:12345/test2");
});
await app.RunAsync();
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"WireMock.Net.TestWebApplication": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:57712;http://localhost:57713"
}
}
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -7,16 +7,16 @@ namespace WireMock.Net.Tests.Facts;
public sealed class IgnoreOnContinuousIntegrationFact : FactAttribute
{
private static readonly string _skipReason = "Ignore when run via CI/CD";
private static readonly bool _isContinuousIntegrationAzure = bool.TryParse(Environment.GetEnvironmentVariable("TF_BUILD"), out var isTF) && isTF;
private static readonly bool _isContinuousIntegrationGithub = bool.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS"), out var isGH) && isGH;
private static bool IsContinuousIntegration() => _isContinuousIntegrationAzure || _isContinuousIntegrationGithub;
private const string SkipReason = "Ignore when run via CI/CD";
private static readonly bool IsContinuousIntegrationAzure = bool.TryParse(Environment.GetEnvironmentVariable("TF_BUILD"), out var isTF) && isTF;
private static readonly bool IsContinuousIntegrationGithub = bool.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS"), out var isGH) && isGH;
private static readonly bool IsContinuousIntegration = IsContinuousIntegrationAzure || IsContinuousIntegrationGithub;
public IgnoreOnContinuousIntegrationFact()
{
if (IsContinuousIntegration())
if (IsContinuousIntegration)
{
Skip = _skipReason;
Skip = SkipReason;
}
}
}
}

View File

@@ -49,6 +49,26 @@ public class HttpRequestMessageHelperTests
Check.That(await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false)).ContainsExactly(Encoding.UTF8.GetBytes("hi"));
}
[Fact]
public async Task HttpRequestMessageHelper_Create_TextPlain()
{
// Assign
var body = new BodyData
{
BodyAsString = "0123", // or 83 in decimal
BodyAsJson = 83,
DetectedBodyType = BodyType.Json,
DetectedBodyTypeFromContentType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body);
// Act
var message = HttpRequestMessageHelper.Create(request, "http://url");
// Assert
Check.That(await message.Content!.ReadAsStringAsync().ConfigureAwait(false)).Equals("0123");
}
[Fact]
public async Task HttpRequestMessageHelper_Create_Json()
{
@@ -64,7 +84,7 @@ public class HttpRequestMessageHelperTests
var message = HttpRequestMessageHelper.Create(request, "http://url");
// Assert
Check.That(await message.Content.ReadAsStringAsync().ConfigureAwait(false)).Equals("{\"x\":42}");
Check.That(await message.Content!.ReadAsStringAsync().ConfigureAwait(false)).Equals("{\"x\":42}");
}
[Fact]

View File

@@ -0,0 +1,111 @@
// Copyright © WireMock.Net
#if NET8_0_OR_GREATER
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WireMock.Net.Xunit;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
using Xunit;
using Xunit.Abstractions;
namespace WireMock.Net.Tests.ResponseBuilders;
public sealed class ResponseWithProxyIntegrationTests(ITestOutputHelper output)
{
[Fact]
public async Task Response_UsingTextPlain()
{
// Given
using var server = await TestServer.New().Run();
var port = server.GetPort();
output.WriteLine($"Server running on port {port}");
var settings = new WireMockServerSettings
{
Port = 0,
Logger = new TestOutputHelperWireMockLogger(output)
};
using var mockServer = WireMockServer.Start(settings);
mockServer.Given(Request.Create().WithPath("/zipcode").UsingPatch())
.RespondWith(Response.Create().WithProxy($"http://localhost:{port}"));
using var client = new HttpClient { BaseAddress = new Uri(mockServer.Urls[0]) };
using var content = new ByteArrayContent("0123"u8.ToArray());
content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
// When
var response = await client.PatchAsync("/zipcode", content);
// Then
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Content.Headers.GetValues("Content-Type").Should().BeEquivalentTo("text/plain; charset=utf-8");
var result = await response.Content.ReadAsStringAsync();
result.Should().Be("0123");
}
sealed class Disposable(Action dispose) : IDisposable
{
public void Dispose() => dispose();
}
sealed class TestServer(WebApplication app) : IDisposable
{
private Disposable _disposable = new(() => { });
public static TestServer New()
{
var builder = WebApplication.CreateBuilder();
builder.WebHost.ConfigureKestrel(opts => opts.ListenAnyIP(0));
var app = builder.Build();
app.MapPatch("/zipcode", async (HttpRequest req) =>
{
var memory = new MemoryStream();
await req.Body.CopyToAsync(memory);
var content = Encoding.UTF8.GetString(memory.ToArray());
return content;
});
return new(app);
}
public int GetPort()
=> app.Services.GetRequiredService<IServer>().Features.Get<IServerAddressesFeature>()!.Addresses
.Select(x => new Uri(x).Port)
.First();
public async ValueTask<TestServer> Run()
{
var started = new TaskCompletionSource();
var host = app.Services.GetRequiredService<IHostApplicationLifetime>();
host.ApplicationStarted.Register(() => started.SetResult());
_ = Task.Run(() => app.RunAsync());
await started.Task;
_disposable = new(() => host.StopApplication());
return this;
}
public void Dispose()
{
_disposable.Dispose();
}
}
}
#endif

View File

@@ -2,6 +2,7 @@
#if NET6_0_OR_GREATER
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Execution;
@@ -13,7 +14,7 @@ namespace WireMock.Net.Tests.Testcontainers;
public class TestcontainersTests
{
[Fact]
public async Task WireMockContainer_Build_and_StartAsync_and_StopAsync()
public async Task WireMockContainer_Build_WithNoImage_And_StartAsync_and_StopAsync()
{
// Act
var adminUsername = $"username_{Guid.NewGuid()}";
@@ -24,6 +25,61 @@ public class TestcontainersTests
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
.Build();
await StartTestAndStopAsync(wireMockContainer);
}
[Fact]
public async Task WireMockContainer_Build_WithImage_And_StartAsync_and_StopAsync()
{
// Arrange
var adminUsername = $"username_{Guid.NewGuid()}";
var adminPassword = $"password_{Guid.NewGuid()}";
var wireMockContainerBuilder = new WireMockContainerBuilder()
.WithAutoRemove(true)
.WithCleanUp(true)
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
wireMockContainerBuilder = wireMockContainerBuilder.WithWindowsImage();
}
else
{
wireMockContainerBuilder = wireMockContainerBuilder.WithLinuxImage();
}
var wireMockContainer = wireMockContainerBuilder.Build();
await StartTestAndStopAsync(wireMockContainer);
}
[Fact]
public async Task WireMockContainer_Build_WithImageAsText_And_StartAsync_and_StopAsync()
{
// Arrange
var adminUsername = $"username_{Guid.NewGuid()}";
var adminPassword = $"password_{Guid.NewGuid()}";
var wireMockContainerBuilder = new WireMockContainerBuilder()
.WithAutoRemove(true)
.WithCleanUp(true)
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net-windows");
}
else
{
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net");
}
var wireMockContainer = wireMockContainerBuilder.Build();
await StartTestAndStopAsync(wireMockContainer);
}
private static async Task StartTestAndStopAsync(WireMockContainer wireMockContainer)
{
try
{
await wireMockContainer.StartAsync().ConfigureAwait(false);

View File

@@ -10,7 +10,8 @@
<PackageId>WireMock.Net.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<ProjectGuid>{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}</ProjectGuid>
<IsTestProject>true</IsTestProject>
<SonarQubeExclude>true</SonarQubeExclude>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>

View File

@@ -11,9 +11,11 @@ using FluentAssertions;
using Moq;
using Newtonsoft.Json;
using NFluent;
using WireMock.Admin.Settings;
using RestEase;
using WireMock.Client;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
@@ -244,6 +246,38 @@ public class WireMockServerAdminTests
loggerMock.Verify(l => l.Info(It.Is<string>(s => s.StartsWith("The Static Mapping folder")), It.IsAny<object[]>()), Times.Once);
}
[Fact]
public async Task WireMockServer_Admin_Mapping_WithoutPathOrUrl()
{
// Arrange
using var server = WireMockServer.StartWithAdminInterface();
// Act
server.Given(Request.Create().UsingGet())
.RespondWith(Response.Create());
// Assert
var mapping = server.Mappings.First(m => !m.IsAdminInterface);
var request = (Request) mapping.RequestMatcher;
var pathMatcher = request.GetRequestMessageMatcher<RequestMessagePathMatcher>();
pathMatcher.Should().BeNull();
var api = RestClient.For<IWireMockAdminApi>(server.Url);
var mappingModels = await api.GetMappingsAsync();
var mappingModel = mappingModels.First();
mappingModel.Request.Path.Should().BeNull();
mappingModel.Request.Url.Should().BeNull();
await api.DeleteMappingsAsync();
await api.PostMappingAsync(mappingModel);
await api.GetMappingsAsync();
mappingModels = await api.GetMappingsAsync();
mappingModel = mappingModels.First();
mappingModel.Request.Path.Should().BeNull();
mappingModel.Request.Url.Should().BeNull();
}
[Fact]
public void WireMockServer_Admin_Mappings_WithGuid_Get()
{

View File

@@ -40,7 +40,7 @@ public partial class WireMockServerTests
{
_testOutputHelper = testOutputHelper;
}
[Fact]
public void WireMockServer_Start()
{
@@ -209,7 +209,7 @@ public partial class WireMockServerTests
.Select(addr => addr.Address.ToString())
.ToArray();
}
[IgnoreOnContinuousIntegrationFact]
public async Task WireMockServer_WithUrl0000_Should_Listen_On_All_IPs_IPv4()
{
@@ -218,22 +218,20 @@ public partial class WireMockServerTests
var IPv4 = GetIPAddressesByFamily(System.Net.Sockets.AddressFamily.InterNetwork);
var settings = new WireMockServerSettings
{
Urls = new string[] { "http://0.0.0.0:" + port },
Urls = ["http://0.0.0.0:" + port],
};
var server = WireMockServer.Start(settings);
using var server = WireMockServer.Start(settings);
server.Given(Request.Create().WithPath("/*")).RespondWith(Response.Create().WithBody("x"));
foreach (var addr in IPv4)
foreach (var address in IPv4)
{
// Act
var response = await new HttpClient().GetStringAsync("http://" + addr + ":" + server.Ports[0] + "/foo").ConfigureAwait(false);
var response = await new HttpClient().GetStringAsync("http://" + address + ":" + server.Ports[0] + "/foo").ConfigureAwait(false);
// Assert
response.Should().Be("x");
}
server.Stop();
}
}
[IgnoreOnContinuousIntegrationFact]
@@ -244,25 +242,23 @@ public partial class WireMockServerTests
var IPv6 = GetIPAddressesByFamily(System.Net.Sockets.AddressFamily.InterNetworkV6);
var settings = new WireMockServerSettings
{
Urls = new string[] { "http://0.0.0.0:" + port },
Urls = ["http://0.0.0.0:" + port],
};
var server = WireMockServer.Start(settings);
using var server = WireMockServer.Start(settings);
server.Given(Request.Create().WithPath("/*")).RespondWith(Response.Create().WithBody("x"));
foreach (var addr in IPv6)
foreach (var address in IPv6)
{
// Act
var response = await new HttpClient().GetStringAsync("http://[" + addr + "]:" + server.Ports[0] + "/foo").ConfigureAwait(false);
var response = await new HttpClient().GetStringAsync("http://[" + address + "]:" + server.Ports[0] + "/foo").ConfigureAwait(false);
// Assert
response.Should().Be("x");
}
server.Stop();
}
#endif
[Fact]
public async Task WireMockServer_Should_respond_a_redirect_without_body()
{