Skip to content

Test Host does not accept trailing commas in launchsettings.json #7975

Open
@afscrome

Description

@afscrome

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

If your app host's launchsettings.json file contains a trailing slash, dotnet run --project MY.AppHost accepts the file, but DistributedApplicationTestingBuilder does not.

Expected Behavior

If a launchsettings.json file works for dotnet run, I'd expect aspire to handle it too.

Steps To Reproduce

  1. Create a new aspire-sample application, and modify the app host's launch settings to include a trailing comma
  2. Do a dotnet run on the apphost project - it starts
  3. Now do a dotnet test on the test project - t fails

launchsettings.json (for apphost)

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "profiles": {
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:17054;http://localhost:15030",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "DOTNET_ENVIRONMENT": "Development",
        "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21224",
        "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22154", // Note the trailing comma here
      }
    }
  }
}

Test

    [Test]
    public async Task MyTest()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AspireInGithubActions_AppHost>();
        await using var app2 = await appHost.BuildAsync();
    }

Exceptions (if any)

      GetWebResourceRootReturnsOkStatusCode (69ms): Error Message: Aspire.Hosting.DistributedApplicationException : Failed to get effective launch profile for project 'S:\AspireInGithubActions\AspireInGithubActions.AppHost'. There is malformed JSON in the project's launch settings file a
      t 'S:\AspireInGithubActions\AspireInGithubActions.AppHost\Properties\launchSettings.json'.
        ----> System.Text.Json.JsonException : The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options. Path: $.profiles.https.environmentVariables | LineNumber: 14 | BytePositionInLine: 6.
        ----> System.Text.Json.JsonReaderException : The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options. LineNumber: 14 | BytePositionInLine: 6.
      Stack Trace:
         at Aspire.Hosting.Testing.DistributedApplicationFactory.GetLaunchSettings(String appHostPath) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 359
         at Aspire.Hosting.Testing.DistributedApplicationFactory.PostConfigureBuilderOptions(HostApplicationBuilderSettings hostBuilderOptions, Assembly entryPointAssembly) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 262
         at Aspire.Hosting.Testing.DistributedApplicationFactory.ConfigureBuilder(String[] args, DistributedApplicationOptions applicationOptions, HostApplicationBuilderSettings hostBuilderOptions, Assembly entryPointAssembly, Action`2 configureBuilder) in /_/src/Aspire.Hosting.Testing/D
      istributedApplicationFactory.cs:line 237
         at Aspire.Hosting.Testing.DistributedApplicationFactory.OnBuilderCreatingCore(DistributedApplicationOptions applicationOptions, HostApplicationBuilderSettings hostBuilderOptions) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 244
         at Aspire.Hosting.Testing.DistributedApplicationEntryPointInvoker.EntryPointInvoker.ApplicationBuilderDiagnosticListener.OnNext(KeyValuePair`2 value) in /_/src/Aspire.Hosting.Testing/DistributedApplicationEntryPointInvoker.cs:line 187
         at System.Diagnostics.DiagnosticListener.Write(String name, Object value)
         at System.Diagnostics.DiagnosticSource.Write[T](String name, T value)
         at Aspire.Hosting.DistributedApplicationBuilder.LogBuilderConstructing(DistributedApplicationOptions appBuilderOptions, HostApplicationBuilderSettings hostBuilderOptions) in /_/src/Aspire.Hosting/DistributedApplicationBuilder.cs:line 488
         at Aspire.Hosting.DistributedApplicationBuilder..ctor(DistributedApplicationOptions options) in /_/src/Aspire.Hosting/DistributedApplicationBuilder.cs:line 135
         at Aspire.Hosting.DistributedApplication.CreateBuilder(String[] args) in /_/src/Aspire.Hosting/DistributedApplication.cs:line 142
         at Program.<Main>$(String[] args) in S:\AspireInGithubActions\AspireInGithubActions.AppHost\Program.cs:line 1
         at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
         at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
      --- End of stack trace from previous location ---
         at Aspire.Hosting.Testing.DistributedApplicationEntryPointInvoker.EntryPointInvoker.InvokeAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting.Testing/DistributedApplicationEntryPointInvoker.cs:line 132
         at Aspire.Hosting.Testing.DistributedApplicationEntryPointInvoker.<>c__DisplayClass0_0.<<ResolveEntryPoint>b__0>d.MoveNext() in /_/src/Aspire.Hosting.Testing/DistributedApplicationEntryPointInvoker.cs:line 39
      --- End of stack trace from previous location ---
         at Aspire.Hosting.Testing.DistributedApplicationFactory.InvokeEntryPoint(Func`3 factory) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 419
         at Aspire.Hosting.Testing.DistributedApplicationFactory.ResolveBuilderAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 51
         at Aspire.Hosting.Testing.DistributedApplicationTestingBuilder.SuspendingDistributedApplicationFactory.CreateBuilderAsync(CancellationToken cancellationToken) in /_/src/Aspire.Hosting.Testing/DistributedApplicationTestingBuilder.cs:line 162
         at Aspire.Hosting.Testing.DistributedApplicationTestingBuilder.CreateAsync(Type entryPoint, String[] args, Action`2 configureBuilder, CancellationToken cancellationToken) in /_/src/Aspire.Hosting.Testing/DistributedApplicationTestingBuilder.cs:line 109
         at AspireInGithubActions.Tests.IntegrationTest1.GetWebResourceRootReturnsOkStatusCode() in S:\AspireInGithubActions\AspireInGithubActions.Tests\IntegrationTest1.cs:line 11
         at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
         at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
         at NUnit.Framework.Internal.AsyncToSyncAdapter.Await[TResult](Func`1 invoke)
         at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
         at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
         at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
         at NUnit.Framework.Internal.Execution.SimpleWorkItem.<>c__DisplayClass3_0.<PerformWork>b__0()
         at NUnit.Framework.Internal.ContextUtils.<>c__DisplayClass1_0`1.<DoIsolated>b__0(Object _)
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
      --- End of stack trace from previous location ---
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
         at NUnit.Framework.Internal.ContextUtils.DoIsolated(ContextCallback callback, Object state)
         at NUnit.Framework.Internal.ContextUtils.DoIsolated[T](Func`1 func)
         at NUnit.Framework.Internal.Execution.SimpleWorkItem.PerformWork()
      --JsonException
         at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
         at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
         at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)
         at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Deserialize(Stream utf8Json)
         at Aspire.Hosting.Testing.DistributedApplicationFactory.GetLaunchSettings(String appHostPath) in /_/src/Aspire.Hosting.Testing/DistributedApplicationFactory.cs:line 353
      --JsonReaderException
         at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
         at System.Text.Json.Utf8JsonReader.ConsumeNextTokenUntilAfterAllCommentsAreSkipped(Byte marker)
         at System.Text.Json.Utf8JsonReader.ConsumeNextToken(Byte marker)
         at System.Text.Json.Utf8JsonReader.ConsumeNextTokenOrRollback(Byte marker)
         at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
         at System.Text.Json.Utf8JsonReader.Read()
         at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TDictionary& value)
         at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
         at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
         at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
         at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
         at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TDictionary& value)
         at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
         at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
         at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
         at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
         at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)

.NET Version info

No response

Anything else?

#5231 Is probably the ultimate solution for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-app-testingIssues pertaining to the APIs in Aspire.Hosting.Testing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions