onebeyond/onebeyond-studio-core

View on GitHub
src/OneBeyond.Studio.Application.SharedKernel.Tests/AmbientContexts/AmbientContextAccessorOverriderTests.cs

Summary

Maintainability
A
2 hrs
Test Coverage
using System;
using Autofac;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using OneBeyond.Studio.Application.SharedKernel.AmbientContexts;
using OneBeyond.Studio.Application.SharedKernel.DependencyInjection;

namespace OneBeyond.Studio.Application.SharedKernel.Tests.AmbientContexts;

[TestClass]
public sealed class AmbientContextAccessorOverriderTests
{
    [TestMethod]
    public void Returns_original_context_when_no_override_provided()
    {
        // Arrange
        var containerBuilder = new ContainerBuilder();
        containerBuilder.AddAmbientContextAccessor<TestableAmbientContextAccessor, TestableAmbientContext>(withOverrider: true);
        var container = containerBuilder.Build();

        // Act
        var ambientContextAccessor = container.Resolve<IAmbientContextAccessor<TestableAmbientContext>>();
        var ambientContext = ambientContextAccessor.AmbientContext;

        // Assert
        Assert.IsInstanceOfType(ambientContextAccessor, typeof(AmbientContextAccessorOverrider<TestableAmbientContext>));
        Assert.AreEqual("42", ambientContext.StringValue);
    }

    [TestMethod]
    public void Returns_context_based_on_override_scope()
    {
        // Arrange
        var containerBuilder = new ContainerBuilder();
        containerBuilder.AddAmbientContextAccessor<TestableAmbientContextAccessor, TestableAmbientContext>(withOverrider: true);
        var container = containerBuilder.Build();
        var outerAmbientContextAccessorMock = new Mock<IAmbientContextAccessor<TestableAmbientContext>>();
        outerAmbientContextAccessorMock
            .Setup((ambientContextAccessor) => ambientContextAccessor.AmbientContext)
            .Returns(new TestableAmbientContext("outer"));
        var outerAmbientContextAccessor = outerAmbientContextAccessorMock.Object;
        var innerAmbientContextAccessorMock = new Mock<IAmbientContextAccessor<TestableAmbientContext>>();
        innerAmbientContextAccessorMock
            .Setup((ambientContextAccessor) => ambientContextAccessor.AmbientContext)
            .Returns(new TestableAmbientContext("inner"));
        var innerAmbientContextAccessor = innerAmbientContextAccessorMock.Object;
        var ambientContextAccessor = container.Resolve<IAmbientContextAccessor<TestableAmbientContext>>();

        // Act
        var outerAmbientContext1 = default(TestableAmbientContext);
        var outerAmbientContext2 = default(TestableAmbientContext);
        var innerAmbientContext1 = default(TestableAmbientContext);
        using (AmbientContextAccessorOverrider<TestableAmbientContext>.OverrideWith(outerAmbientContextAccessor))
        {
            outerAmbientContext1 = ambientContextAccessor.AmbientContext;

            using (AmbientContextAccessorOverrider<TestableAmbientContext>.OverrideWith(innerAmbientContextAccessor))
            {
                innerAmbientContext1 = ambientContextAccessor.AmbientContext;
            }

            outerAmbientContext2 = ambientContextAccessor.AmbientContext;
        }

        // Assert
        Assert.AreEqual("outer", outerAmbientContext1.StringValue);
        Assert.AreEqual("outer", outerAmbientContext2.StringValue);
        Assert.AreEqual("inner", innerAmbientContext1.StringValue);
    }

    [TestMethod]
    public void Throws_when_override_scope_disposing_is_broken()
    {
        // Arrange
        var containerBuilder = new ContainerBuilder();
        containerBuilder.AddAmbientContextAccessor<TestableAmbientContextAccessor, TestableAmbientContext>(withOverrider: true);
        var container = containerBuilder.Build();
        var outerAmbientContextAccessorMock = new Mock<IAmbientContextAccessor<TestableAmbientContext>>();
        outerAmbientContextAccessorMock
            .Setup((ambientContextAccessor) => ambientContextAccessor.AmbientContext)
            .Returns(new TestableAmbientContext("outer"));
        var outerAmbientContextAccessor = outerAmbientContextAccessorMock.Object;
        var innerAmbientContextAccessorMock = new Mock<IAmbientContextAccessor<TestableAmbientContext>>();
        innerAmbientContextAccessorMock
            .Setup((ambientContextAccessor) => ambientContextAccessor.AmbientContext)
            .Returns(new TestableAmbientContext("inner"));
        var innerAmbientContextAccessor = innerAmbientContextAccessorMock.Object;
        var ambientContextAccessor = container.Resolve<IAmbientContextAccessor<TestableAmbientContext>>();

        // Act
        var globalAmbientContext = ambientContextAccessor.AmbientContext;
        var invalidOperationException = default(InvalidOperationException);
        using (var outerOverride = AmbientContextAccessorOverrider<TestableAmbientContext>.OverrideWith(outerAmbientContextAccessor))
        using (var innerOverride = AmbientContextAccessorOverrider<TestableAmbientContext>.OverrideWith(innerAmbientContextAccessor))
        {
            try
            {
                outerOverride.Dispose();
            }
            catch (InvalidOperationException exception)
            {
                invalidOperationException = exception;
            }
        }

        // Assert
        Assert.IsNotNull(invalidOperationException, nameof(invalidOperationException));
        Assert.AreEqual("Ambient context accessor overriding order is broken.", invalidOperationException?.Message);
        Assert.AreEqual("42", globalAmbientContext.StringValue);
    }
}