C
C#•6mo ago
kmanjt

Testcontainers CosmosDB / WebApplication Factory ConnectionString Not Working

anyone familiar with WebApplicationFactory / Testcontainers? The below is giving me System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0.
public abstract class IntegrationTest
{
protected readonly HttpClient TestClient;
protected CosmosDbContainer cosmosDbContainer;

protected IntegrationTest()
{
cosmosDbContainer = new CosmosDbBuilder()
.WithImage("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")
.Build();
cosmosDbContainer.StartAsync().GetAwaiter().GetResult();

var appFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var connectionString = cosmosDbContainer.GetConnectionString();
var cosmosOptions = new CosmosClientOptions()
{
Serializer = new CosmosJsonSerializer()
};
services.RemoveAll(typeof(CosmosClient));
services.AddSingleton(new CosmosClient(connectionString, cosmosOptions));
});

builder.UseEnvironment("Development");
});

TestClient = appFactory.CreateClient();
}

public void Dispose()
{
cosmosDbContainer.DisposeAsync();
}
}
public abstract class IntegrationTest
{
protected readonly HttpClient TestClient;
protected CosmosDbContainer cosmosDbContainer;

protected IntegrationTest()
{
cosmosDbContainer = new CosmosDbBuilder()
.WithImage("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")
.Build();
cosmosDbContainer.StartAsync().GetAwaiter().GetResult();

var appFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var connectionString = cosmosDbContainer.GetConnectionString();
var cosmosOptions = new CosmosClientOptions()
{
Serializer = new CosmosJsonSerializer()
};
services.RemoveAll(typeof(CosmosClient));
services.AddSingleton(new CosmosClient(connectionString, cosmosOptions));
});

builder.UseEnvironment("Development");
});

TestClient = appFactory.CreateClient();
}

public void Dispose()
{
cosmosDbContainer.DisposeAsync();
}
}
someone mentioned ports earlier?
14 Replies
Exploding Hams
Exploding Hams•6mo ago
I've used it a bit, but without knowing which line threw the exception in particular, I would caution that when using the web application factory will call the entry point in your Program class. If you have any startup code there, you may need to override any and all initialization you're doing within the builder.ConfigureServices(_ => { }) method. Alternatively, it could be the connection string formatting from similar exception messages
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
kmanjt
kmanjtOP•6mo ago
kmanjt
kmanjtOP•6mo ago
I have changed it to this, which is still not working (and containers are not disposing properly either):
public abstract class IntegrationTest : IDisposable
{
protected readonly HttpClient TestClient;
private readonly CosmosDbContainer _cosmosDbContainer = new CosmosDbBuilder()
.WithPortBinding(0, 8081)
.Build();

protected IntegrationTest()
{
TestClient = InitializeClient().GetAwaiter().GetResult();
}

public async Task InitializeAsync()
{
await _cosmosDbContainer.StartAsync();
Console.WriteLine($"Mapped public port for Cosmos DB: {_cosmosDbContainer.GetMappedPublicPort(8081)}");
}

public async Task DisposeAsync()
{
await _cosmosDbContainer.DisposeAsync().AsTask();
}

private async Task<HttpClient> InitializeClient()
{
await InitializeAsync();
var appFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var connectionString = _cosmosDbContainer.GetConnectionString();
Console.WriteLine($"Connection string generated: {connectionString}");

var cosmosOptions = new CosmosClientOptions
{
Serializer = new CosmosJsonSerializer(),
ConnectionMode = ConnectionMode.Gateway,
HttpClientFactory = () => _cosmosDbContainer.HttpClient
};

services.RemoveAll(typeof(CosmosClient));
services.AddSingleton(new CosmosClient(connectionString, cosmosOptions));
});

builder.UseEnvironment("Development");
});

return appFactory.CreateClient();
}


public void Dispose()
{
TestClient.Dispose();
DisposeAsync().GetAwaiter().GetResult();
}
public abstract class IntegrationTest : IDisposable
{
protected readonly HttpClient TestClient;
private readonly CosmosDbContainer _cosmosDbContainer = new CosmosDbBuilder()
.WithPortBinding(0, 8081)
.Build();

protected IntegrationTest()
{
TestClient = InitializeClient().GetAwaiter().GetResult();
}

public async Task InitializeAsync()
{
await _cosmosDbContainer.StartAsync();
Console.WriteLine($"Mapped public port for Cosmos DB: {_cosmosDbContainer.GetMappedPublicPort(8081)}");
}

public async Task DisposeAsync()
{
await _cosmosDbContainer.DisposeAsync().AsTask();
}

private async Task<HttpClient> InitializeClient()
{
await InitializeAsync();
var appFactory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
var connectionString = _cosmosDbContainer.GetConnectionString();
Console.WriteLine($"Connection string generated: {connectionString}");

var cosmosOptions = new CosmosClientOptions
{
Serializer = new CosmosJsonSerializer(),
ConnectionMode = ConnectionMode.Gateway,
HttpClientFactory = () => _cosmosDbContainer.HttpClient
};

services.RemoveAll(typeof(CosmosClient));
services.AddSingleton(new CosmosClient(connectionString, cosmosOptions));
});

builder.UseEnvironment("Development");
});

return appFactory.CreateClient();
}


public void Dispose()
{
TestClient.Dispose();
DisposeAsync().GetAwaiter().GetResult();
}
TilionDC
TilionDC•6mo ago
You sure its not the connectionstring thats poorly formatted?
kmanjt
kmanjtOP•6mo ago
Mapped public port for Cosmos DB: 56685 Connection string generated: AccountEndpoint=https://127.0.0.1:56685/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
TilionDC
TilionDC•6mo ago
https://www.connectionstrings.com/sql-server/ I'm no connectionstring expert but try take a look at this. What dbserver are you using?
SQL Server connection strings - ConnectionStrings.com
Connection strings for SQL Server. Connect using Microsoft.Data.SqlClient, SqlConnection, MSOLEDBSQL, SQLNCLI11 OLEDB, SQLNCLI10 OLEDB, SQLNCLI OLEDB.
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
TilionDC
TilionDC•6mo ago
sorry, my brain is mushy today
TilionDC
TilionDC•6mo ago
https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/how-to-dotnet-get-started?tabs=azure-cli%2Cwindows If it doesn't work the DI way. Try creating an azurecredential and see if you can make a dbclient that way
Get started with Azure Cosmos DB for NoSQL using .NET
Get started developing a .NET application that works with Azure Cosmos DB for NoSQL. This article helps you learn how to set up a project and configure access to an Azure Cosmos DB for NoSQL endpoint.
kmanjt
kmanjtOP•6mo ago
sorry I am confused how that relates here, here is my Program.cs setup for CosmosDB:
builder.Services.AddSingleton<CosmosClient>(cosmosClient => new CosmosClient(cosmosConfig.ConnectionString, new CosmosClientOptions()
{
ApplicationRegion = cosmosConfig.ApplicationRegion,
}));

builder.Services.AddAzureClients(clientsBuilder =>
{
clientsBuilder.AddClient<CosmosClient, CosmosClientOptions>(options =>
{
options.Serializer = new CosmosJsonSerializer();
options.ApplicationRegion = cosmosConfig.ApplicationRegion;
return new CosmosClient(cosmosConfig.ConnectionString, options);
})
.WithName(cosmosConfig.CosmosDbClientName);
});
builder.Services.AddSingleton<CosmosClient>(cosmosClient => new CosmosClient(cosmosConfig.ConnectionString, new CosmosClientOptions()
{
ApplicationRegion = cosmosConfig.ApplicationRegion,
}));

builder.Services.AddAzureClients(clientsBuilder =>
{
clientsBuilder.AddClient<CosmosClient, CosmosClientOptions>(options =>
{
options.Serializer = new CosmosJsonSerializer();
options.ApplicationRegion = cosmosConfig.ApplicationRegion;
return new CosmosClient(cosmosConfig.ConnectionString, options);
})
.WithName(cosmosConfig.CosmosDbClientName);
});
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
kmanjt
kmanjtOP•6mo ago
bump still no success 😦 Ok so the weird thing is, this seems to be an issue with how I am instantiating my cosmos client Not to do with Testcontainers itself The exception is actually being thrown here in my Program.cs:
clientsBuilder.AddClient<CosmosClient, CosmosClientOptions>(options =>
{
options.Serializer = new CosmosJsonSerializer();
options.ApplicationRegion = cosmosConfig.ApplicationRegion;
return new CosmosClient(cosmosConfig.ConnectionString, options);
})
clientsBuilder.AddClient<CosmosClient, CosmosClientOptions>(options =>
{
options.Serializer = new CosmosJsonSerializer();
options.ApplicationRegion = cosmosConfig.ApplicationRegion;
return new CosmosClient(cosmosConfig.ConnectionString, options);
})
Exploding Hams
Exploding Hams•6mo ago
Yeah definitely a bum connection string. usually you wouldn't have the IP address like that, it's probably expecting localhost instead (I'll admit I may be a dummy but just a guess), CosmosClient when instantiated will look to make a real connection outwards otherwise you would need to make an actual connection to a hosted cosmos db instance, or are you running the emulator? try specifying the values through the constructor properties so you can rule whether it's straight up formatting giving you trouble:
using CosmosClient client = new(
accountEndpoint: "https://localhost:56685/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
using CosmosClient client = new(
accountEndpoint: "https://localhost:56685/",
authKeyOrResourceToken: "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
);
Want results from more Discord servers?
Add your server