Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Moq.AutoMock.Tests/Resolvers/BaseResolverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Moq.AutoMock.Resolvers;

namespace Moq.AutoMock.Tests.Resolvers;

public abstract class BaseResolverTests<TResolver> where TResolver : IMockResolver, new()
{
protected static MockResolutionContext Resolve<TRequestedType>(AutoMocker mocker)
=> Resolve<TRequestedType>(mocker, new TResolver());

protected static MockResolutionContext Resolve<TRequestedType>(AutoMocker mocker, IMockResolver resolver)
=> Resolve(mocker, typeof(TRequestedType), resolver);

protected static MockResolutionContext Resolve(AutoMocker mocker, Type requestedType, IMockResolver resolver)
{
var context = new MockResolutionContext(mocker, requestedType, new ObjectGraphContext(false));
resolver.Resolve(context);
return context;
}
}
122 changes: 122 additions & 0 deletions Moq.AutoMock.Tests/Resolvers/InsertResolverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using Moq.AutoMock.Resolvers;

namespace Moq.AutoMock.Tests.Resolvers;

[TestClass]
public class InsertResolverTests
{
[TestMethod]
public void InsertResolverAfter_WhenTargetResolverExists_InsertsAfterTarget()
{
var mocker = new AutoMocker();
var originalResolvers = mocker.Resolvers.ToList();
int selfResolverIndex = originalResolvers.FindIndex(r => r is SelfResolver);
var newResolver = new TestResolver();

mocker.InsertResolverAfter<SelfResolver>(newResolver);

Assert.HasCount(originalResolvers.Count + 1, mocker.Resolvers);
Assert.AreSame(newResolver, mocker.Resolvers[selfResolverIndex + 1]);
}

[TestMethod]
public void InsertResolverAfter_WhenTargetIsLastResolver_InsertsAtEnd()
{
var mocker = new AutoMocker();
var lastResolver = mocker.Resolvers[^1];
int originalCount = mocker.Resolvers.Count;
var newResolver = new TestResolver();

Assert.IsInstanceOfType<MockResolver>(lastResolver);
mocker.InsertResolverAfter<MockResolver>(newResolver);

Assert.HasCount(originalCount + 1, mocker.Resolvers);
Assert.AreSame(newResolver, mocker.Resolvers[^1]);
}

[TestMethod]
public void InsertResolverAfter_WhenTargetNotFound_ThrowsInvalidOperationException()
{
var mocker = new AutoMocker();
var newResolver = new TestResolver();

var ex = Assert.Throws<InvalidOperationException>(
() => mocker.InsertResolverAfter<TestResolver>(newResolver));

Assert.Contains(nameof(TestResolver), ex.Message);
}

[TestMethod]
public void InsertResolverAfter_WhenTargetIsFirstResolver_InsertsAtSecondPosition()
{
var mocker = new AutoMocker();
var newResolver = new TestResolver();

Assert.IsInstanceOfType<CacheResolver>(mocker.Resolvers[0]);
mocker.InsertResolverAfter<CacheResolver>(newResolver);

Assert.AreSame(newResolver, mocker.Resolvers[1]);
Assert.IsInstanceOfType<CacheResolver>(mocker.Resolvers[0]);
}

[TestMethod]
public void InsertResolverBefore_WhenTargetResolverExists_InsertsBeforeTarget()
{
var mocker = new AutoMocker();
var originalResolvers = mocker.Resolvers.ToList();
int mockResolverIndex = originalResolvers.FindIndex(r => r is MockResolver);
var newResolver = new TestResolver();

mocker.InsertResolverBefore<MockResolver>(newResolver);

Assert.HasCount(originalResolvers.Count + 1, mocker.Resolvers);
Assert.AreSame(newResolver, mocker.Resolvers[mockResolverIndex]);
Assert.IsInstanceOfType<MockResolver>(mocker.Resolvers[mockResolverIndex + 1]);
}

[TestMethod]
public void InsertResolverBefore_WhenTargetIsFirstResolver_InsertsAtBeginning()
{
var mocker = new AutoMocker();
int originalCount = mocker.Resolvers.Count;
var newResolver = new TestResolver();

// CacheResolver is the first resolver in the default list
mocker.InsertResolverBefore<CacheResolver>(newResolver);

Assert.HasCount(originalCount + 1, mocker.Resolvers);
Assert.AreSame(newResolver, mocker.Resolvers[0]);
Assert.IsInstanceOfType<CacheResolver>(mocker.Resolvers[1]);
}

[TestMethod]
public void InsertResolverBefore_WhenTargetNotFound_ThrowsInvalidOperationException()
{
var mocker = new AutoMocker();
var newResolver = new TestResolver();

var ex = Assert.Throws<InvalidOperationException>(
() => mocker.InsertResolverBefore<TestResolver>(newResolver));

Assert.Contains(nameof(TestResolver), ex.Message);
}

[TestMethod]
public void InsertResolverBefore_WhenTargetIsLastResolver_InsertsBeforeLast()
{
var mocker = new AutoMocker();
int originalCount = mocker.Resolvers.Count;
var newResolver = new TestResolver();

mocker.InsertResolverBefore<MockResolver>(newResolver);

Assert.HasCount(originalCount + 1, mocker.Resolvers);
Assert.AreSame(newResolver, mocker.Resolvers[^2]);
Assert.IsInstanceOfType<MockResolver>(mocker.Resolvers[^1]);
}

private class TestResolver : IMockResolver
{
public void Resolve(MockResolutionContext context) { }
}
}
29 changes: 29 additions & 0 deletions Moq.AutoMock.Tests/Resolvers/SelfResolverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Moq.AutoMock.Resolvers;

namespace Moq.AutoMock.Tests.Resolvers;

[TestClass]
public class SelfResolverTests : BaseResolverTests<SelfResolver>
{
[TestMethod]
public void WhenRequestTypeIsAutoMockerThenResolvesToAutoMockerInstance()
{
var mocker = new AutoMocker();

var context = Resolve<AutoMocker>(mocker);

Assert.IsTrue(context.ValueProvided);
Assert.AreSame(mocker, context.Value);
}

[TestMethod]
public void WhenRequestTypeIsIServiceProviderThenResolvesToAutoMockerInstance()
{
var mocker = new AutoMocker();

var context = Resolve<IServiceProvider>(mocker);

Assert.IsTrue(context.ValueProvided);
Assert.AreSame(mocker, context.Value);
}
}
147 changes: 147 additions & 0 deletions Moq.AutoMock.Tests/Resolvers/SimpleTypeResolverTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using Moq.AutoMock.Resolvers;

namespace Moq.AutoMock.Tests.Resolvers;

[TestClass]
public class SimpleTypeResolverTests : BaseResolverTests<SimpleTypeResolverTests.TestSimpleTypeResolver>
{
[TestMethod]
public void WhenRequestTypeMatchesExactlyThenResolves()
{
var mocker = new AutoMocker();

var context = Resolve<TestDerived>(mocker);

Assert.IsTrue(context.ValueProvided);
Assert.IsInstanceOfType<TestDerived>(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsAssignableToTAndIncludeBaseTypesIsTrueThenResolves()
{
var mocker = new AutoMocker();
var resolver = new DerivedSimpleTypeResolver { TestIncludeBaseTypes = true };

var context = Resolve<TestDerived>(mocker, resolver);

Assert.IsTrue(context.ValueProvided);
Assert.IsInstanceOfType<TestBase>(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsAssignableToTAndIncludeBaseTypesIsFalseThenDoesNotResolve()
{
var mocker = new AutoMocker();
var resolver = new DerivedSimpleTypeResolver { TestIncludeBaseTypes = false };

var context = Resolve<TestDerived>(mocker, resolver);

Assert.IsFalse(context.ValueProvided);
Assert.IsNull(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsBaseTypeAndIncludeBaseTypesIsTrueThenDoesNotResolve()
{
var mocker = new AutoMocker();
var resolver = new TestSimpleTypeResolver { TestIncludeBaseTypes = true };

var context = Resolve<TestBase>(mocker, resolver);

Assert.IsFalse(context.ValueProvided);
Assert.IsNull(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsInterfaceAndIncludeInterfacesIsTrueThenResolves()
{
var mocker = new AutoMocker();
var resolver = new TestSimpleTypeResolver { TestIncludeInterfaces = true };

var context = Resolve<ITestInterface>(mocker, resolver);

Assert.IsTrue(context.ValueProvided);
Assert.IsInstanceOfType<TestDerived>(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsInterfaceAndIncludeInterfacesIsFalseThenDoesNotResolve()
{
var mocker = new AutoMocker();
var resolver = new TestSimpleTypeResolver { TestIncludeInterfaces = false };

var context = Resolve<ITestInterface>(mocker, resolver);

Assert.IsFalse(context.ValueProvided);
Assert.IsNull(context.Value);
}

[TestMethod]
public void WhenRequestTypeIsUnrelatedThenDoesNotResolve()
{
var mocker = new AutoMocker();

var context = Resolve<string>(mocker);

Assert.IsFalse(context.ValueProvided);
Assert.IsNull(context.Value);
}

[TestMethod]
public void WhenBothIncludesAreFalseAndRequestTypeIsExactMatchThenResolves()
{
var mocker = new AutoMocker();
var resolver = new TestSimpleTypeResolver { TestIncludeBaseTypes = false, TestIncludeInterfaces = false };

var context = Resolve<TestDerived>(mocker, resolver);

Assert.IsTrue(context.ValueProvided);
Assert.IsInstanceOfType<TestDerived>(context.Value);
}

public interface ITestInterface { }

public class TestBase { }

public class TestDerived : TestBase, ITestInterface { }

public class TestSimpleTypeResolver : SimpleTypeResolver<TestDerived>
{
public bool TestIncludeBaseTypes
{
get => IncludeBaseTypes;
set => IncludeBaseTypes = value;
}

public bool TestIncludeInterfaces
{
get => IncludeInterfaces;
set => IncludeInterfaces = value;
}

protected override TestDerived GetValue(MockResolutionContext context)
{
return new TestDerived();
}
}

private class DerivedSimpleTypeResolver : SimpleTypeResolver<TestBase>
{
public bool TestIncludeBaseTypes
{
get => IncludeBaseTypes;
set => IncludeBaseTypes = value;
}

public bool TestIncludeInterfaces
{
get => IncludeInterfaces;
set => IncludeInterfaces = value;
}

protected override TestBase GetValue(MockResolutionContext context)
{
return new TestBase();
}
}
}
47 changes: 47 additions & 0 deletions Moq.AutoMock/AutoMocker.Resolvers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Moq.AutoMock.Resolvers;

namespace Moq.AutoMock;

public partial class AutoMocker
{
/// <summary>
/// Inserts a resolver after the first occurrence of a resolver of type <typeparamref name="TResolver"/> in the resolver list.
/// </summary>
/// <typeparam name="TResolver">The target resolve to insert after.</typeparam>
/// <param name="resolver">The new resolver to add.</param>
/// <returns>This <see cref="AutoMocker"/> instances</returns>
/// <exception cref="InvalidOperationException">Thrown when no resolver instance of type <typeparamref name="TResolver"/> is found</exception>
public AutoMocker InsertResolverAfter<TResolver>(IMockResolver resolver) where TResolver : IMockResolver
{
for (int i = 0; i < Resolvers.Count; i++)
{
if (Resolvers[i] is TResolver)
{
Resolvers.Insert(i + 1, resolver);
return this;
}
}
throw new InvalidOperationException($"Could not find resolve of type {typeof(TResolver).FullName} in {nameof(AutoMocker)} instance");
}

/// <summary>
/// Inserts a resolver before the first occurrence of a resolver of type <typeparamref name="TResolver"/> in the resolver list.
/// </summary>
/// <typeparam name="TResolver">The target resolve to insert before.</typeparam>
/// <param name="resolver">The new resolver to add.</param>
/// <returns>This <see cref="AutoMocker"/> instances</returns>
/// <exception cref="InvalidOperationException">Thrown when no resolver instance of type <typeparamref name="TResolver"/> is found</exception>
public AutoMocker InsertResolverBefore<TResolver>(IMockResolver resolver)
where TResolver : IMockResolver
{
for (int i = 0; i < Resolvers.Count; i++)
{
if (Resolvers[i] is TResolver)
{
Resolvers.Insert(i, resolver);
return this;
}
}
throw new InvalidOperationException($"Could not find resolve of type {typeof(TResolver).FullName} in {nameof(AutoMocker)} instance");
}
}
13 changes: 5 additions & 8 deletions Moq.AutoMock/Resolvers/HttpClientResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ namespace Moq.AutoMock.Resolvers;
/// <summary>
/// A resolver that can provide HttpClients with mocked HttpMessageHandler.
/// </summary>
public class HttpClientResolver : IMockResolver
public class HttpClientResolver : SimpleTypeResolver<HttpClient>
{
/// <inheritdoc />
public void Resolve(MockResolutionContext context)
protected override HttpClient GetValue(MockResolutionContext context)
{
if (context.RequestType == typeof(HttpClient))
{
var messageHandler = context.AutoMocker.GetMock<HttpMessageHandler>();
messageHandler.DefaultValueProvider = HttpMessageHandlerDefaultValueProvider.Instance;
context.Value = messageHandler.CreateClient();
}
var messageHandler = context.AutoMocker.GetMock<HttpMessageHandler>();
messageHandler.DefaultValueProvider = HttpMessageHandlerDefaultValueProvider.Instance;
return messageHandler.CreateClient();
}

/// <summary>
Expand Down
Loading
Loading