Add an launch inspector command to Aspire Dashboard (#1283)

* Upgrade to Aspire 9.2.0

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* Remove workload installs from CI pipeline

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* Missed package upgrade

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* Fix usings

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* Add Open Inspector command

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* Fix broken test

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* PR comments

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

* More PR comments

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>

---------

Signed-off-by: Jonathan Mezach <jonathan.mezach@rr-wfm.com>
This commit is contained in:
Jonathan Mezach
2025-04-25 20:23:19 +02:00
committed by GitHub
parent 9392069f8a
commit 8a07286b89
9 changed files with 706 additions and 618 deletions

View File

@@ -1,185 +1,176 @@
variables: variables:
Prerelease: 'ci' Prerelease: 'ci'
buildId: "1$(Build.BuildId)" buildId: "1$(Build.BuildId)"
buildProjects: '**/src/**/*.csproj' buildProjects: '**/src/**/*.csproj'
jobs: jobs:
- job: Linux_Build_Test_SonarCloud - job: Linux_Build_Test_SonarCloud
pool: pool:
vmImage: 'ubuntu-22.04' vmImage: 'ubuntu-22.04'
steps: steps:
- script: | - script: |
echo "BuildId = $(buildId)" echo "BuildId = $(buildId)"
displayName: 'Print buildId' displayName: 'Print buildId'
- task: CmdLine@2 - script: |
displayName: 'Install .NET Aspire workload' dotnet tool install --global dotnet-sonarscanner
inputs: dotnet tool install --global dotnet-coverage
script: 'dotnet workload install aspire' displayName: 'Install dotnet tools'
- script: | - task: PowerShell@2
dotnet tool install --global dotnet-sonarscanner displayName: "Use JDK17 by default"
dotnet tool install --global dotnet-coverage inputs:
displayName: 'Install dotnet tools' targetType: 'inline'
script: |
- script: | $jdkPath = $env:JAVA_HOME_17_X64
dotnet workload install aspire Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath"
displayName: 'Install aspire'
- script: |
- task: PowerShell@2 dotnet dev-certs https --trust || true
displayName: "Use JDK17 by default" displayName: 'dotnet dev-certs https'
inputs:
targetType: 'inline' # See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage
script: | - script: |
$jdkPath = $env:JAVA_HOME_17_X64 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
Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath" displayName: 'Begin analysis on SonarCloud'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- script: |
dotnet dev-certs https --trust || true - task: DotNetCoreCLI@2
displayName: 'dotnet dev-certs https' displayName: 'Build Unit tests'
inputs:
# See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage command: 'build'
- script: | projects: '**/test/**/*.csproj'
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 arguments: '--configuration Debug --framework net8.0'
displayName: 'Begin analysis on SonarCloud'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests - task: CmdLine@2
inputs:
- task: DotNetCoreCLI@2 script: |
displayName: 'Build Unit tests' 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"
inputs: displayName: 'WireMock.Net.Tests with Coverage'
command: 'build'
projects: '**/test/**/*.csproj' - task: CmdLine@2
arguments: '--configuration Debug --framework net8.0' inputs:
script: |
- task: CmdLine@2 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"
inputs: displayName: 'WireMock.Net.TUnitTests with Coverage'
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-xunit.xml" - task: CmdLine@2
displayName: 'WireMock.Net.Tests with Coverage' inputs:
script: |
- task: CmdLine@2 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"
inputs: displayName: 'WireMock.Net.Middleware.Tests with Coverage'
script: |
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" - task: CmdLine@2
displayName: 'WireMock.Net.TUnitTests with Coverage' inputs:
script: |
- task: CmdLine@2 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"
inputs: displayName: 'WireMock.Net.Aspire.Tests with Coverage'
script: |
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" - task: CmdLine@2
displayName: 'WireMock.Net.Middleware.Tests with Coverage' displayName: 'Merge coverage files'
inputs:
- task: CmdLine@2 script: 'dotnet coverage merge **/wiremock-coverage-*.xml --output ./test/wiremock-coverage.xml --output-format xml'
inputs:
script: | - 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-aspire.xml" dotnet sonarscanner end /d:sonar.token="$(SONAR_TOKEN)"
displayName: 'WireMock.Net.Aspire.Tests with Coverage' displayName: 'End analysis on SonarCloud'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- task: CmdLine@2
displayName: 'Merge coverage files' - task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
inputs: displayName: 'WhiteSource Bolt'
script: 'dotnet coverage merge **/wiremock-coverage-*.xml --output ./test/wiremock-coverage.xml --output-format xml' condition: and(succeeded(), eq(variables['RUN_WHITESOURCE'], 'yes'))
- script: | - script: |
dotnet sonarscanner end /d:sonar.token="$(SONAR_TOKEN)" bash <(curl https://codecov.io/bash) -t $(CODECOV_TOKEN) -f ./test/wiremock-coverage.xml
displayName: 'End analysis on SonarCloud' displayName: 'Upload coverage results to codecov'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- task: PublishTestResults@2
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19 condition: and(succeeded(), eq(variables['PUBLISH_TESTRESULTS'], 'yes'))
displayName: 'WhiteSource Bolt' inputs:
condition: and(succeeded(), eq(variables['RUN_WHITESOURCE'], 'yes')) testRunner: VSTest
testResultsFiles: '**/*.trx'
- script: |
bash <(curl https://codecov.io/bash) -t $(CODECOV_TOKEN) -f ./test/wiremock-coverage.xml - task: PublishBuildArtifacts@1
displayName: 'Upload coverage results to codecov' displayName: Publish coverage files
inputs:
- task: PublishTestResults@2 PathtoPublish: './test/WireMock.Net.Tests/coverage.net8.0.opencover.xml'
condition: and(succeeded(), eq(variables['PUBLISH_TESTRESULTS'], 'yes'))
inputs: - job: Windows_Build_Test
testRunner: VSTest
testResultsFiles: '**/*.trx' pool:
vmImage: 'windows-2022'
- task: PublishBuildArtifacts@1
displayName: Publish coverage files steps:
inputs: - task: UseDotNet@2
PathtoPublish: './test/WireMock.Net.Tests/coverage.net8.0.opencover.xml' displayName: Use .NET 8.0
inputs:
- job: Windows_Build_Test packageType: 'sdk'
version: '8.0.x'
pool:
vmImage: 'windows-2022' - task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Tests with Coverage'
steps: inputs:
- task: UseDotNet@2 command: 'test'
displayName: Use .NET 8.0 projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
inputs: arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
packageType: 'sdk'
version: '8.0.x' - task: DotNetCoreCLI@2
displayName: 'WireMock.Net.TUnitTests with Coverage'
- task: DotNetCoreCLI@2 inputs:
displayName: 'WireMock.Net.Tests with Coverage' command: 'test'
inputs: projects: './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj'
command: 'test' arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx' - task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
- task: DotNetCoreCLI@2 inputs:
displayName: 'WireMock.Net.TUnitTests with Coverage' command: 'test'
inputs: projects: './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj'
command: 'test' arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
projects: './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj'
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx' - job: Windows_Release_to_MyGet
dependsOn: Windows_Build_Test
- task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Middleware.Tests with Coverage' pool:
inputs: vmImage: 'windows-2022'
command: 'test'
projects: './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' steps:
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx' - task: UseDotNet@2
displayName: Use .NET 8.0
- job: Windows_Release_to_MyGet inputs:
dependsOn: Windows_Build_Test packageType: 'sdk'
version: '8.0.x'
pool:
vmImage: 'windows-2022' - task: DotNetCoreCLI@2
displayName: Build Release
steps: inputs:
- task: UseDotNet@2 command: 'build'
displayName: Use .NET 8.0 arguments: /p:Configuration=Release
inputs: projects: $(buildProjects)
packageType: 'sdk'
version: '8.0.x' - task: DotNetCoreCLI@2
displayName: Pack
- task: DotNetCoreCLI@2 condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
displayName: Build Release inputs:
inputs: command: pack
command: 'build' configuration: 'Release'
arguments: /p:Configuration=Release packagesToPack: $(buildProjects)
projects: $(buildProjects) nobuild: true
packDirectory: '$(Build.ArtifactStagingDirectory)/packages'
- task: DotNetCoreCLI@2 verbosityPack: 'normal'
displayName: Pack
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests - task: PublishBuildArtifacts@1
inputs: displayName: Publish Artifacts
command: pack condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
configuration: 'Release' inputs:
packagesToPack: $(buildProjects) PathtoPublish: '$(Build.ArtifactStagingDirectory)'
nobuild: true
packDirectory: '$(Build.ArtifactStagingDirectory)/packages' - task: DotNetCoreCLI@2
verbosityPack: 'normal' displayName: Push to MyGet
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- task: PublishBuildArtifacts@1 inputs:
displayName: Publish Artifacts command: custom
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests custom: nuget
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
- task: DotNetCoreCLI@2
displayName: Push to MyGet
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
inputs:
command: custom
custom: nuget
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg -n -s https://www.myget.org/F/wiremock-net/api/v3/index.json -k $(MyGetKey) arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg -n -s https://www.myget.org/F/wiremock-net/api/v3/index.json -k $(MyGetKey)

View File

@@ -1,23 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <OutputType>Exe</OutputType>
<Nullable>enable</Nullable> <TargetFramework>net8.0</TargetFramework>
<IsAspireHost>true</IsAspireHost> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AspireApp1.ApiService\AspireApp1.ApiService.csproj" /> <ItemGroup>
<ProjectReference Include="..\AspireApp1.Web\AspireApp1.Web.csproj" /> <ProjectReference Include="..\AspireApp1.ApiService\AspireApp1.ApiService.csproj" />
<ProjectReference Include="..\AspireApp1.Web\AspireApp1.Web.csproj" />
<!-- https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-resources?tabs=windows#create-library-for-resource-extension -->
<ProjectReference Include="..\..\src\WireMock.Net.Aspire\WireMock.Net.Aspire.csproj" IsAspireProjectResource="false" /> <!-- https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-resources?tabs=windows#create-library-for-resource-extension -->
</ItemGroup> <ProjectReference Include="..\..\src\WireMock.Net.Aspire\WireMock.Net.Aspire.csproj" IsAspireProjectResource="false" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.0" /> <ItemGroup>
</ItemGroup> <PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,20 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <OutputType>Exe</OutputType>
<Nullable>enable</Nullable> <TargetFramework>net8.0</TargetFramework>
<IsAspireHost>true</IsAspireHost> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AspireApp1.ApiService\AspireApp1.ApiService.csproj" /> <ItemGroup>
<ProjectReference Include="..\AspireApp1.Web\AspireApp1.Web.csproj" /> <ProjectReference Include="..\AspireApp1.ApiService\AspireApp1.ApiService.csproj" />
</ItemGroup> <ProjectReference Include="..\AspireApp1.Web\AspireApp1.Web.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.0" /> <ItemGroup>
</ItemGroup> <PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,49 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Description>Aspire extension to start a WireMock.Net server to stub an api.</Description> <Description>Aspire extension to start a WireMock.Net server to stub an api.</Description>
<AssemblyTitle>WireMock.Net.Aspire</AssemblyTitle> <AssemblyTitle>WireMock.Net.Aspire</AssemblyTitle>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net.Aspire</AssemblyName> <AssemblyName>WireMock.Net.Aspire</AssemblyName>
<PackageId>WireMock.Net.Aspire</PackageId> <PackageId>WireMock.Net.Aspire</PackageId>
<PackageTags>dotnet;aspire;wiremock;extension</PackageTags> <PackageTags>dotnet;aspire;wiremock;extension</PackageTags>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A12}</ProjectGuid> <ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A12}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources> <EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign> <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>WireMock.Net-LogoAspire.png</PackageIcon> <PackageIcon>WireMock.Net-LogoAspire.png</PackageIcon>
<ApplicationIcon>../../resources/WireMock.Net-LogoAspire.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-LogoAspire.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="../../resources/WireMock.Net-Logo.png" /> <None Remove="../../resources/WireMock.Net-Logo.png" />
<None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" /> <None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" /> <Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Aspire.Hosting" Version="8.2.2" /> <PackageReference Include="Aspire.Hosting" Version="9.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" /> <ProjectReference Include="..\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,43 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Aspire.Hosting.WireMock;
internal static class WireMockInspector
{
/// <summary>
/// Opens the WireMockInspector tool to inspect the WireMock server.
/// </summary>
/// <param name="wireMockUrl"></param>
/// <param name="title"></param>
/// <exception cref="InvalidOperationException"></exception>
/// <remarks>
/// Copy of <see href="https://github.com/WireMock-Net/WireMockInspector/blob/main/src/WireMock.Net.Extensions.WireMockInspector/WireMockServerExtensions.cs" />
/// without requestFilters and no call to WaitForExit() method in the process so it doesn't block the caller.
/// </remarks>
public static void Inspect(string wireMockUrl, [CallerMemberName] string title = "")
{
try
{
var arguments = $"attach --adminUrl {wireMockUrl} --autoLoad --instanceName \"{title}\"";
Process.Start(new ProcessStartInfo
{
FileName = "wiremockinspector",
Arguments = arguments,
UseShellExecute = false
});
}
catch (Exception e)
{
throw new InvalidOperationException
(
message: @"Cannot find installation of WireMockInspector.
Execute the following command to install WireMockInspector dotnet tool:
> dotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources
To get more info please visit https://github.com/WireMock-Net/WireMockInspector",
innerException: e
);
}
}
}

View File

@@ -1,175 +1,222 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Lifecycle; using Aspire.Hosting.Lifecycle;
using Stef.Validation; using Aspire.Hosting.WireMock;
using WireMock.Client.Builders; using Microsoft.Extensions.Diagnostics.HealthChecks;
using WireMock.Net.Aspire; using Stef.Validation;
using WireMock.Client.Builders;
// ReSharper disable once CheckNamespace using WireMock.Net.Aspire;
namespace Aspire.Hosting;
// ReSharper disable once CheckNamespace
/// <summary> namespace Aspire.Hosting;
/// Provides extension methods for adding WireMock.Net Server resources to the application model.
/// </summary> /// <summary>
public static class WireMockServerBuilderExtensions /// Provides extension methods for adding WireMock.Net Server resources to the application model.
{ /// </summary>
// Linux only (https://github.com/dotnet/aspire/issues/854) public static class WireMockServerBuilderExtensions
private const string DefaultLinuxImage = "sheyenrath/wiremock.net-alpine"; {
private const string DefaultLinuxMappingsPath = "/app/__admin/mappings"; // Linux only (https://github.com/dotnet/aspire/issues/854)
private const string DefaultLinuxImage = "sheyenrath/wiremock.net-alpine";
/// <summary> private const string DefaultLinuxMappingsPath = "/app/__admin/mappings";
/// Adds a WireMock.Net Server resource to the application model.
/// </summary> /// <summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> /// Adds a WireMock.Net Server resource to the application model.
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> /// </summary>
/// <param name="port">The HTTP port for the WireMock Server.</param> /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, int? port = null) /// <param name="port">The HTTP port for the WireMock Server.</param>
{ /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
Guard.NotNull(builder); public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, int? port = null)
Guard.NotNullOrWhiteSpace(name); {
Guard.Condition(port, p => p is null or > 0 and <= ushort.MaxValue); Guard.NotNull(builder);
Guard.NotNullOrWhiteSpace(name);
return builder.AddWireMock(name, callback => Guard.Condition(port, p => p is null or > 0 and <= ushort.MaxValue);
{
callback.HttpPort = port; return builder.AddWireMock(name, callback =>
}); {
} callback.HttpPort = port;
});
/// <summary> }
/// Adds a WireMock.Net Server resource to the application model.
/// </summary> /// <summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> /// Adds a WireMock.Net Server resource to the application model.
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> /// </summary>
/// <param name="arguments">The arguments to start the WireMock.Net Server.</param> /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, WireMockServerArguments arguments) /// <param name="arguments">The arguments to start the WireMock.Net Server.</param>
{ /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
Guard.NotNull(builder); public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, WireMockServerArguments arguments)
Guard.NotNullOrWhiteSpace(name); {
Guard.NotNull(arguments); Guard.NotNull(builder);
Guard.NotNullOrWhiteSpace(name);
var wireMockContainerResource = new WireMockServerResource(name, arguments); Guard.NotNull(arguments);
var resourceBuilder = builder
.AddResource(wireMockContainerResource) var wireMockContainerResource = new WireMockServerResource(name, arguments);
.WithImage(DefaultLinuxImage) var resourceBuilder = builder
.WithEnvironment(ctx => ctx.EnvironmentVariables.Add("DOTNET_USE_POLLING_FILE_WATCHER", "1")) // https://khalidabuhakmeh.com/aspnet-docker-gotchas-and-workarounds#configuration-reloads-and-filesystemwatcher .AddResource(wireMockContainerResource)
.WithHttpEndpoint(port: arguments.HttpPort, targetPort: WireMockServerArguments.HttpContainerPort); .WithImage(DefaultLinuxImage)
.WithEnvironment(ctx => ctx.EnvironmentVariables.Add("DOTNET_USE_POLLING_FILE_WATCHER", "1")) // https://khalidabuhakmeh.com/aspnet-docker-gotchas-and-workarounds#configuration-reloads-and-filesystemwatcher
if (!string.IsNullOrEmpty(arguments.MappingsPath)) .WithHttpEndpoint(port: arguments.HttpPort, targetPort: WireMockServerArguments.HttpContainerPort)
{ .WithWireMockInspectorCommand();
resourceBuilder = resourceBuilder.WithBindMount(arguments.MappingsPath, DefaultLinuxMappingsPath);
} if (!string.IsNullOrEmpty(arguments.MappingsPath))
{
resourceBuilder = resourceBuilder.WithArgs(ctx => resourceBuilder = resourceBuilder.WithBindMount(arguments.MappingsPath, DefaultLinuxMappingsPath);
{ }
foreach (var arg in arguments.GetArgs())
{ resourceBuilder = resourceBuilder.WithArgs(ctx =>
ctx.Args.Add(arg); {
} foreach (var arg in arguments.GetArgs())
}); {
ctx.Args.Add(arg);
return resourceBuilder; }
} });
/// <summary> return resourceBuilder;
/// Adds a WireMock.Net Server resource to the application model. }
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> /// <summary>
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param> /// Adds a WireMock.Net Server resource to the application model.
/// <param name="callback">A callback that allows for setting the <see cref="WireMockServerArguments"/>.</param> /// </summary>
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, Action<WireMockServerArguments> callback) /// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
{ /// <param name="callback">A callback that allows for setting the <see cref="WireMockServerArguments"/>.</param>
Guard.NotNull(builder); /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
Guard.NotNullOrWhiteSpace(name); public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, Action<WireMockServerArguments> callback)
Guard.NotNull(callback); {
Guard.NotNull(builder);
var arguments = new WireMockServerArguments(); Guard.NotNullOrWhiteSpace(name);
callback(arguments); Guard.NotNull(callback);
return builder.AddWireMock(name, arguments); var arguments = new WireMockServerArguments();
} callback(arguments);
/// <summary> return builder.AddWireMock(name, arguments);
/// Defines if the static mappings should be read at startup. }
///
/// Default set to <c>false</c>. /// <summary>
/// </summary> /// Defines if the static mappings should be read at startup.
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> ///
public static IResourceBuilder<WireMockServerResource> WithReadStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock) /// Default set to <c>false</c>.
{ /// </summary>
Guard.NotNull(wiremock).Resource.Arguments.ReadStaticMappings = true; /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
return wiremock; public static IResourceBuilder<WireMockServerResource> WithReadStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock)
} {
Guard.NotNull(wiremock).Resource.Arguments.ReadStaticMappings = true;
/// <summary> return wiremock;
/// Watch the static mapping files + folder for changes when running. }
///
/// Default set to <c>false</c>. /// <summary>
/// </summary> /// Watch the static mapping files + folder for changes when running.
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> ///
public static IResourceBuilder<WireMockServerResource> WithWatchStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock) /// Default set to <c>false</c>.
{ /// </summary>
Guard.NotNull(wiremock).Resource.Arguments.WatchStaticMappings = true; /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
return wiremock; public static IResourceBuilder<WireMockServerResource> WithWatchStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock)
} {
Guard.NotNull(wiremock).Resource.Arguments.WatchStaticMappings = true;
/// <summary> return wiremock;
/// Specifies the path for the (static) mapping json files. }
/// </summary>
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param> /// <summary>
/// <param name="mappingsPath">The local path.</param> /// Specifies the path for the (static) mapping json files.
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> /// </summary>
public static IResourceBuilder<WireMockServerResource> WithMappingsPath(this IResourceBuilder<WireMockServerResource> wiremock, string mappingsPath) /// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
{ /// <param name="mappingsPath">The local path.</param>
Guard.NotNullOrWhiteSpace(mappingsPath); /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
Guard.NotNull(wiremock).Resource.Arguments.MappingsPath = mappingsPath; public static IResourceBuilder<WireMockServerResource> WithMappingsPath(this IResourceBuilder<WireMockServerResource> wiremock, string mappingsPath)
{
return wiremock.WithBindMount(mappingsPath, DefaultLinuxMappingsPath); Guard.NotNullOrWhiteSpace(mappingsPath);
} Guard.NotNull(wiremock).Resource.Arguments.MappingsPath = mappingsPath;
/// <summary> return wiremock.WithBindMount(mappingsPath, DefaultLinuxMappingsPath);
/// Set the admin username and password for accessing the admin interface from WireMock.Net via HTTP. }
/// </summary>
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param> /// <summary>
/// <param name="username">The admin username.</param> /// Set the admin username and password for accessing the admin interface from WireMock.Net via HTTP.
/// <param name="password">The admin password.</param> /// </summary>
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns> /// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
public static IResourceBuilder<WireMockServerResource> WithAdminUserNameAndPassword(this IResourceBuilder<WireMockServerResource> wiremock, string username, string password) /// <param name="username">The admin username.</param>
{ /// <param name="password">The admin password.</param>
Guard.NotNull(wiremock); /// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
public static IResourceBuilder<WireMockServerResource> WithAdminUserNameAndPassword(this IResourceBuilder<WireMockServerResource> wiremock, string username, string password)
wiremock.Resource.Arguments.AdminUsername = Guard.NotNull(username); {
wiremock.Resource.Arguments.AdminPassword = Guard.NotNull(password); Guard.NotNull(wiremock);
return wiremock;
} wiremock.Resource.Arguments.AdminUsername = Guard.NotNull(username);
wiremock.Resource.Arguments.AdminPassword = Guard.NotNull(password);
/// <summary> return wiremock;
/// Use WireMock Client's AdminApiMappingBuilder to configure the WireMock.Net resource. }
/// </summary>
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param> /// <summary>
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param> /// Use WireMock Client's AdminApiMappingBuilder to configure the WireMock.Net resource.
/// <returns></returns> /// </summary>
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, Task> configure) /// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
{ /// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
return wiremock.WithApiMappingBuilder((adminApiMappingBuilder, _) => configure.Invoke(adminApiMappingBuilder)); /// <returns></returns>
} public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, Task> configure)
{
/// <summary> return wiremock.WithApiMappingBuilder((adminApiMappingBuilder, _) => configure.Invoke(adminApiMappingBuilder));
/// Use WireMock Client's AdminApiMappingBuilder to configure the WireMock.Net resource. }
/// </summary>
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param> /// <summary>
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param> /// Use WireMock Client's AdminApiMappingBuilder to configure the WireMock.Net resource.
/// <returns></returns> /// </summary>
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure) /// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
{ /// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
Guard.NotNull(wiremock); /// <returns></returns>
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure)
wiremock.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>(); {
wiremock.Resource.Arguments.ApiMappingBuilder = configure; Guard.NotNull(wiremock);
return wiremock; wiremock.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>();
} wiremock.Resource.Arguments.ApiMappingBuilder = configure;
return wiremock;
}
/// <summary>
/// Enables the WireMockInspect, a cross-platform UI app that facilitates WireMock troubleshooting.
/// This requires installation of the WireMockInspector tool.
/// <code>
/// dotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources
/// </code>
/// </summary>
/// <param name="builder">The <see cref="IResourceBuilder{WireMockNetResource}"/>.</param>
/// <returns></returns>
public static IResourceBuilder<WireMockServerResource> WithWireMockInspectorCommand(this IResourceBuilder<WireMockServerResource> builder)
{
Guard.NotNull(builder);
CommandOptions commandOptions = new()
{
Description = "Requires installation of the WireMockInspector (https://github.com/WireMock-Net/WireMockInspector) tool:\ndotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources",
UpdateState = OnUpdateResourceState,
IconName = "BoxSearch",
IconVariant = IconVariant.Filled
};
builder.WithCommand(
name: "wiremock-inspector",
displayName: "WireMock Inspector",
executeCommand: context => OnRunOpenInspectorCommandAsync(builder),
commandOptions: commandOptions);
return builder;
}
private static Task<ExecuteCommandResult> OnRunOpenInspectorCommandAsync(IResourceBuilder<WireMockServerResource> builder)
{
WireMockInspector.Inspect(builder.Resource.GetEndpoint().Url);
return Task.FromResult(CommandResults.Success());
}
private static ResourceCommandState OnUpdateResourceState(UpdateCommandStateContext context)
{
return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
? ResourceCommandState.Enabled
: ResourceCommandState.Disabled;
}
} }

View File

@@ -1,30 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings> <OutputType>Exe</OutputType>
<Nullable>enable</Nullable> <TargetFramework>net8.0</TargetFramework>
<IsAspireHost>true</IsAspireHost> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign> <AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> <PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<ItemGroup>
<!-- https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-resources?tabs=windows#create-library-for-resource-extension --> <ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Aspire\WireMock.Net.Aspire.csproj" IsAspireProjectResource="false" /> <!-- https://learn.microsoft.com/en-us/dotnet/aspire/extensibility/custom-resources?tabs=windows#create-library-for-resource-extension -->
</ItemGroup> <ProjectReference Include="..\..\src\WireMock.Net.Aspire\WireMock.Net.Aspire.csproj" IsAspireProjectResource="false" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.2" /> <ItemGroup>
</ItemGroup> <PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="WireMockMappings\*.json"> <ItemGroup>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <None Update="WireMockMappings\*.json">
</None> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</ItemGroup> </None>
</ItemGroup>
</Project> </Project>

View File

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

View File

@@ -1,96 +1,98 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using System.Net.Sockets; using System.Net.Sockets;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
namespace WireMock.Net.Aspire.Tests; namespace WireMock.Net.Aspire.Tests;
public class WireMockServerBuilderExtensionsTests public class WireMockServerBuilderExtensionsTests
{ {
[Theory] [Theory]
[InlineData(null)] [InlineData(null)]
[InlineData("")] [InlineData("")]
[InlineData(" ")] [InlineData(" ")]
[InlineData("\t")] [InlineData("\t")]
public void AddWireMock_WithNullOrWhiteSpaceName_ShouldThrowException(string? name) public void AddWireMock_WithNullOrWhiteSpaceName_ShouldThrowException(string? name)
{ {
// Arrange // Arrange
var builder = Mock.Of<IDistributedApplicationBuilder>(); var builder = Mock.Of<IDistributedApplicationBuilder>();
// Act // Act
Action act = () => builder.AddWireMock(name!, 12345); Action act = () => builder.AddWireMock(name!, 12345);
// Assert // Assert
act.Should().Throw<Exception>(); act.Should().Throw<Exception>();
} }
[Fact] [Fact]
public void AddWireMock_WithInvalidPort_ShouldThrowArgumentOutOfRangeException() public void AddWireMock_WithInvalidPort_ShouldThrowArgumentOutOfRangeException()
{ {
// Arrange // Arrange
const int invalidPort = -1; const int invalidPort = -1;
var builder = Mock.Of<IDistributedApplicationBuilder>(); var builder = Mock.Of<IDistributedApplicationBuilder>();
// Act // Act
Action act = () => builder.AddWireMock("ValidName", invalidPort); Action act = () => builder.AddWireMock("ValidName", invalidPort);
// Assert // Assert
act.Should().Throw<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values. (Parameter 'port')"); act.Should().Throw<ArgumentOutOfRangeException>().WithMessage("Specified argument was out of the range of valid values. (Parameter 'port')");
} }
[Fact] [Fact]
public void AddWireMock() public void AddWireMock()
{ {
// Arrange // Arrange
var name = $"apiservice{Guid.NewGuid()}"; var name = $"apiservice{Guid.NewGuid()}";
const int port = 12345; const int port = 12345;
const string username = "admin"; const string username = "admin";
const string password = "test"; const string password = "test";
var builder = DistributedApplication.CreateBuilder(); var builder = DistributedApplication.CreateBuilder();
// Act // Act
var wiremock = builder var wiremock = builder
.AddWireMock(name, port) .AddWireMock(name, port)
.WithAdminUserNameAndPassword(username, password) .WithAdminUserNameAndPassword(username, password)
.WithReadStaticMappings(); .WithReadStaticMappings();
// Assert // Assert
wiremock.Resource.Should().NotBeNull(); wiremock.Resource.Should().NotBeNull();
wiremock.Resource.Name.Should().Be(name); wiremock.Resource.Name.Should().Be(name);
wiremock.Resource.Arguments.Should().BeEquivalentTo(new WireMockServerArguments wiremock.Resource.Arguments.Should().BeEquivalentTo(new WireMockServerArguments
{ {
AdminPassword = password, AdminPassword = password,
AdminUsername = username, AdminUsername = username,
ReadStaticMappings = true, ReadStaticMappings = true,
WatchStaticMappings = false, WatchStaticMappings = false,
MappingsPath = null, MappingsPath = null,
HttpPort = port HttpPort = port
}); });
wiremock.Resource.Annotations.Should().HaveCount(4); wiremock.Resource.Annotations.Should().HaveCount(5);
var containerImageAnnotation = wiremock.Resource.Annotations.OfType<ContainerImageAnnotation>().FirstOrDefault(); var containerImageAnnotation = wiremock.Resource.Annotations.OfType<ContainerImageAnnotation>().FirstOrDefault();
containerImageAnnotation.Should().BeEquivalentTo(new ContainerImageAnnotation containerImageAnnotation.Should().BeEquivalentTo(new ContainerImageAnnotation
{ {
Image = "sheyenrath/wiremock.net-alpine", Image = "sheyenrath/wiremock.net-alpine",
Registry = null, Registry = null,
Tag = "latest" Tag = "latest"
}); });
var endpointAnnotation = wiremock.Resource.Annotations.OfType<EndpointAnnotation>().FirstOrDefault(); var endpointAnnotation = wiremock.Resource.Annotations.OfType<EndpointAnnotation>().FirstOrDefault();
endpointAnnotation.Should().BeEquivalentTo(new EndpointAnnotation( endpointAnnotation.Should().BeEquivalentTo(new EndpointAnnotation(
protocol: ProtocolType.Tcp, protocol: ProtocolType.Tcp,
uriScheme: "http", uriScheme: "http",
transport: null, transport: null,
name: null, name: null,
port: port, port: port,
targetPort: 80, targetPort: 80,
isExternal: null, isExternal: null,
isProxied: true isProxied: true
)); ));
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull(); wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull(); wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
}
wiremock.Resource.Annotations.OfType<ResourceCommandAnnotation>().FirstOrDefault().Should().NotBeNull();
}
} }