Cosmos DB
The Arcus.Testing.Storage.Cosmos
package provides test fixtures to Azure Cosmos DB storage. By using the common test practices 'clean environment', it provides a temporary collections and documents.
Installation
The following functionality is available when installing this package:
PM> Install-Package -Name Arcus.Testing.Storage.Cosmos
- MongoDB
- NoSQL
Make sure that the test client that interacts with the Azure Cosmos DB storage has at least DocumentDB Account Contributor
-rights if the test needs to create/update/delete collections.
Temporary MongoDB collection
The TemporaryMongoDbCollection
provides a solution when the integration test requires a storage system (collection) during the test run. An Azure Cosmos DB for MongoDB collection is created upon setup of the test fixture and is deleted again when the test fixture disposed.
⚡ The test fixture automatically uses an existing MongoDB collection - if exists, but does not remove it if it was not responsible for creating the collection.
using Arcus.Testing;
ResourceIdentifier cosmosDbAccountResourceId =
CosmosDBAccountResource.CreateResourceIdentifier("<subscription-id>", "<resource-group>", "<account-name>");
await using var collection = await TemporaryMongoDbCollection.CreateIfNotExistsAsync(
cosmosDbAccountResourceId,
"<database-name>",
"<collection-name>",
logger);
// Interact with the collection during the lifetime of the fixture.
IMongoCollection<Shipment> client = collection.GetCollectionClient<Shipment>();
🎖️ Overloads are available that takes in the
IMongoDatabase
for custom authentication mechanisms. By default, it uses theDefaultAzureCredential
.
Upserting documents in the collection can also be done via the test fixture. It always make sure that any upserted documents are removed (if new) or reverted (if existing) afterwards.
using Arcus.Testing;
await using TemporaryMongoDbCollection collection = ...
await collection.UpsertDocumentAsync(new Shipment { BoatName = "The Alice" });
The TemporaryMongoDbCollection
will always remove/revert any MongoDB documents that were upserted via the temporary collection itself with the collection.UpsertDocumentAsync
. This follows the 'clean environment' testing principal that any test should not leave any state it created behind after the test has run.
Customization
The setup and teardown process of the temporary collection is configurable. By default, it always removes any resources that it was responsible for creating.
using Arcus.Testing;
await TemporaryMongoDbCollection.CreateIfNotExistsAsync(..., options =>
{
// Options related to when the test fixture is set up.
// ---------------------------------------------------
// (Default) Leaves all existing MongoDB documents untouched when the test fixture is created.
options.OnSetup.LeaveAllDocuments();
// Delete all MongoDB documents that already existed before the test fixture creation, when there was already a MongoDB collection available.
options.OnSetup.CleanAllDocuments();
// Delete all MongoDB documents that matches any of the configured filters,
// upon the test fixture creation, when there was already a MongoDB collection available.
options.OnSetup.CleanMatchingDocuments(
Builders<Shipment>.Filter.Eq(s => s.BoatName, "The Alice"));
options.OnSetup.CleanMatchingDocuments((Shipment s) => s.BoatName == "The Alice");
// Options related to when the test fixture is teared down.
// --------------------------------------------------------
// (Default) Delete/Revert all MongoDB documents that were upserted by the test fixture.
options.OnTeardown.CleanUpsertedDocuments();
// Delete all MongoDB documents upon the test fixture disposal,
// even if the test fixture didn't upserted them.
options.OnTeardown.CleanAllDocuments();
// Delete all MongoDB documents that matches any of the configured filters,
// upon the test fixture disposal, even if the test fixture didn't upserted them.
// ⚠️ MongoDb documents upserted by the test fixture will be deleted/reverted, even if the documents don't match the configured filters.
options.OnTeardown.CleanMatchingDocuments(
Builders<Shipment>.Filter.Eq(s => s.BoatName, "The Alice"));
options.OnTeardown.CleanMatchingDocuments((Shipment s) => s.BoatName == "The Alice");
});
// `OnTeardown` is also still available after the temporary collection is created:
await using TemporaryMongoDbCollection collection = ...
collection.OnTeardown.CleanAllDocuments();
Temporary MongoDB document
The TemporaryMongoDbDocument
provides a solution when the integration test requires a document during the test run. A MongoDB document is created upon the setup of the test fixture and is deleted again when the test fixture is disposed.
When the document already existed (already a document with a same configured document ID), then the test fixture will revert to the original content of the document upon the test fixture disposal.
⚡ Whether or not the test fixture should use an existing document is set by using an existing document ID (
_id
by default).
using Arcus.Testing;
ResourceIdentifier cosmosDbAccountResourceId =
CosmosDBAccountResource.CreateResourceIdentifier("<subscription-id>", "<resource-group>", "<account-name>");
var shipment = new Shipment { BoatName = "The Alice" };
await using var document = await TemporaryMongoDbDocument.UpsertDocumentAsync(
cosmosDbAccountResourceId,
"<database-name>",
"<collection-name>",
shipment,
logger);
BsonValue documentId = document.Id;
Make sure that the test client that interacts with the Cosmos storage has at least Cosmos DB Built-in Data Contributor
-rights if the test needs to create/update/delete containers.
This role is not a built-in Azure RBAC, but a role specific for NoSQL. One can assign this role with Azure CLI:
PS> az cosmosdb sql role assignment create `
--account-name "CosmosDBAccountName" `
--resource-group "ResourceGroupName" `
--role-definition-name "Cosmos DB Built-in Data Contributor" `
--scope "/" `
--principal-id "UserOrPrincipalObjectId"
Temporary NoSQL container
The TemporaryNoSqlContainer
provides a solution when the integration tes requires a storage system (container) during the test run. An Azure Cosmos DB for NoSQL container is created upon setup of the test fixture and is deleted again when the test fixture disposed.
⚡ The test fixture automatically uses an existing container - if exists, but does not remove it if it was not responsible for creating the container.
using Arcus.Testing;
ResourceIdentifier cosmosDbAccountResourceId =
CosmosDBAccountResource.CreateResourceIdentifier("<subscription-id>", "<resource-group>", "<account-name>");
await using var container = await TemporaryNoSqlContainer.CreateIfNotExistsAsync(
cosmosDbAccountResourceId,
"<database-name>",
"<container-name>",
"/partition-key-path",
logger);
// Interact with the container during the lifetime of the fixture.
Container client = container.Client;
🎖️ Overloads are available for custom authentication mechanisms. By default, it uses the
DefaultAzureCredential
.
Upserting items in the container can also be done via the test fixture. It always make sure that any upserted items are removed (if new) or reverted (if existing) afterwards.
using Arcus.Testing;
await using TemporaryNoSqlContainer container = ...
await container.UpsertItemAsync(new Shipment { Id = "123", BoatName = "The Alice" });
The TemporaryNoSqlContainer
will always remove/revert any NoSql items that were upserted via the temporary container itself with the container.UpsertItemAsync
. This follows the 'clean environment' testing principal that any test should not leave any state it created behind after the test has run.
Customization
The setup and teardown process of the temporary container is configurable. By default, it always removes any resources that it was responsible for creating.
using Arcus.Testing;
await TemporaryNoSqlContainer.CreateIfNotExistsAsync(..., options =>
{
// Options related to when the test fixture is set up.
// ---------------------------------------------------
// (Default) Leaves all existing NoSQL items untouched when the test fixture is created.
options.OnSetup.LeaveAllItems();
// Delete all NoSQL items that already existed before the test fixture creation, when there was already a NoSQL container available.
options.OnSetup.CleanAllItems();
// Delete all NoSQL items that matches any of the configured filters,
// upon the test fixture creation, when there was already a NoSql container available.
options.OnSetup.CleanMatchingItems((NoSqlItem item) => item.Id == "123");
options.OnSetup.CleanMatchingItems((Shipment item) => item.BoatName == "The Alice");
// Options related to when the test fixture is teared down.
// --------------------------------------------------------
// (Default) Delete/Revert all NoSql items that were upserted by the test fixture.
options.OnTeardown.CleanUpsertedItems();
// Delete all NoSQL items upon the test fixture disposal,
// even if the test fixture didn't upserted them.
options.OnTeardown.CleanAllItems();
// Delete all NoSQL items that matches any of the configured filters,
// upon the test fixture disposal, even if the test fixture didn't upserted them.
// ⚠️ NoSql items upserted by the test fixture will be deleted/reverted, even if the items don't match the configured filters.
options.OnTeardown.CleanMatchingItems((NoSqlItem item) => item.Id == "123");
options.OnTeardown.CleanMatchingItems((Shipment item) => item.BoatName == "The Alice");
});
// `OnTeardown` is also still available after the temporary container is created:
await using TemporaryNoSqlContainer container = ...
container.OnTeardown.CleanAllItems();
Temporary NoSQL item
The TemporaryNoSqlItem
provides a solution when the integration test requires a item during the test run. A NoSQL item is created upon the setup of the test fixture and is deleted again when the test fixture is disposed.
⚡ When the item already existed (already a item with a same configured item ID), then the test fixture will revert to the original content of the item upon the test fixture disposal.
using Arcus.Testing;
Container containerClient = ...
var shipment = new Shipment { Id = "123", BoatName = "The Alice" };
await using var item = await TemporaryNoSqlItem.UpsertItemAsync(
containerClient, shipment, logger);
string itemId = item.Id;
PartitionKey partitionKey = item.PartitionKey;