Skip to content

Commit

Permalink
Fix mapping during CreateInstance
Browse files Browse the repository at this point in the history
  • Loading branch information
cwinland committed Aug 31, 2023
1 parent 69604d2 commit 1e4ead2
Show file tree
Hide file tree
Showing 8 changed files with 591 additions and 359 deletions.
723 changes: 439 additions & 284 deletions FastMoq.Core/Mocker.cs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion FastMoq.Core/Models/ConstructorModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace FastMoq.Models
/// <summary>
/// Class ConstructorModel.
/// </summary>
internal class ConstructorModel
public class ConstructorModel : IHistoryModel
{
#region Properties

Expand Down
6 changes: 6 additions & 0 deletions FastMoq.Core/Models/IHistoryModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace FastMoq.Models
{
public interface IHistoryModel
{
}
}
30 changes: 30 additions & 0 deletions FastMoq.Core/Models/IInstanceModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace FastMoq.Models
{
/// <summary>
/// Interface IInstanceModel
/// </summary>
public interface IInstanceModel : IHistoryModel
{
#region Properties

/// <summary>
/// Gets the type.
/// </summary>
/// <value>The type.</value>
Type Type { get; }

/// <summary>
/// Gets the create function.
/// </summary>
/// <value>The create function.</value>
Func<Mocker, object>? CreateFunc { get; }

/// <summary>
/// Gets the type of the instance.
/// </summary>
/// <value>The type of the instance.</value>
Type InstanceType { get; }

#endregion
}
}
94 changes: 27 additions & 67 deletions FastMoq.Core/Models/InstanceModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,108 +2,68 @@

namespace FastMoq.Models
{
/// <inheritdoc />
/// <summary>
/// Class InstanceModel.
/// Implements the <see cref="T:FastMoq.InstanceModel" />
/// Implements the <see cref="T:FastMoq.Models.InstanceModel" />
/// </summary>
/// <typeparam name="TClass">The type of the t class.</typeparam>
/// <seealso cref="T:FastMoq.InstanceModel" />
/// <inheritdoc cref="IHistoryModel" />
/// <inheritdoc cref="IInstanceModel" />
/// <seealso cref="T:FastMoq.Models.InstanceModel" />
[ExcludeFromCodeCoverage]
public class InstanceModel<TClass> : InstanceModel where TClass : class
public class InstanceModel : IInstanceModel
{
#region Properties

/// <summary>
/// Gets or sets the create function.
/// </summary>
/// <value>The create function.</value>
public new Func<Mocker, TClass>? CreateFunc
{
get => (Func<Mocker, TClass>?)base.CreateFunc;
set => base.CreateFunc = value;
}

#endregion

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel`1" /> class.
/// </summary>
public InstanceModel() : this(null) { }
public virtual Type Type { get; }

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel`1" /> class.
/// </summary>
/// <param name="createFunc">The create function.</param>
public InstanceModel(Func<Mocker, TClass>? createFunc) : base(typeof(TClass), createFunc) { }
public virtual Type InstanceType { get; }

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="InstanceModel{TClass}"/> class.
/// </summary>
/// <param name="createFunc">The create function.</param>
/// <param name="arguments">The arguments.</param>
public InstanceModel(Func<Mocker, TClass>? createFunc, List<object> arguments) : this(createFunc) =>
Arguments = arguments;
}

/// <summary>
/// Class InstanceModel.
/// Implements the <see cref="InstanceModel" />
/// </summary>
/// <seealso cref="InstanceModel" />
[ExcludeFromCodeCoverage]
public class InstanceModel
{
#region Properties

/// <summary>
/// Gets or sets the type of the instance.
/// </summary>
/// <value>The type of the instance.</value>
public Type InstanceType { get; }

/// <summary>
/// Gets or sets the create function.
/// </summary>
/// <value>The create function.</value>
public Func<Mocker, object>? CreateFunc { get; internal set; }

/// <summary>
/// Gets the arguments.
/// </summary>
/// <value>The arguments.</value>
public List<object> Arguments { get; internal set; } = new();
public List<object?> Arguments { get; internal set; } = new();

#endregion

/// <summary>
/// Initializes a new instance of the <see cref="InstanceModel" /> class.
/// </summary>
/// <param name="originalType">Type of the original.</param>
/// <param name="instanceType">Type of the instance.</param>
/// <exception cref="ArgumentNullException">instanceType</exception>
internal InstanceModel(Type instanceType) =>
internal InstanceModel(Type originalType, Type instanceType)
{
Type = originalType;
InstanceType = instanceType ?? throw new ArgumentNullException(nameof(instanceType));
}

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel" /> class.
/// Initializes a new instance of the <see cref="InstanceModel"/> class.
/// </summary>
/// <param name="originalType">Type of the original.</param>
/// <param name="instanceType">Type of the instance.</param>
/// <param name="createFunc"></param>
/// <exception cref="T:System.ArgumentNullException">arguments</exception>
internal InstanceModel(Type instanceType, Func<Mocker, object>? createFunc) : this(instanceType) => CreateFunc = createFunc;

/// <param name="createFunc">The create function.</param>
/// <inheritdoc />
internal InstanceModel(Type originalType, Type instanceType, Func<Mocker, object>? createFunc) : this(originalType, instanceType)
=> CreateFunc = createFunc;

/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel" /> class.
/// Initializes a new instance of the <see cref="InstanceModel"/> class.
/// </summary>
/// <param name="originalType">Type of the original.</param>
/// <param name="instanceType">Type of the instance.</param>
/// <param name="createFunc"></param>
/// <param name="createFunc">The create function.</param>
/// <param name="arguments">The arguments.</param>
/// <exception cref="T:System.ArgumentNullException">arguments</exception>
internal InstanceModel(Type instanceType, Func<Mocker, object>? createFunc, List<object> arguments) : this(instanceType, createFunc) => Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments));
/// <exception cref="ArgumentNullException">arguments</exception>
/// <inheritdoc />
internal InstanceModel(Type originalType, Type instanceType, Func<Mocker, object>? createFunc, List<object?> arguments)
: this(originalType, instanceType, createFunc) =>
Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments));
}
}
61 changes: 61 additions & 0 deletions FastMoq.Core/Models/InstanceModelT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.Diagnostics.CodeAnalysis;

namespace FastMoq.Models
{
/// <inheritdoc />
/// <summary>
/// Class InstanceModel.
/// Implements the <see cref="T:FastMoq.InstanceModel" />
/// </summary>
/// <typeparam name="TClass">The type of the t class.</typeparam>
/// <seealso cref="T:FastMoq.InstanceModel" />
[ExcludeFromCodeCoverage]
public class InstanceModel<TClass> : InstanceModel where TClass : class
{
#region Properties

/// <inheritdoc />
public override Type InstanceType => typeof(TClass);

/// <summary>
/// Gets or sets the create function.
/// </summary>
/// <value>The create function.</value>
public new Func<Mocker, TClass>? CreateFunc
{
get => (Func<Mocker, TClass>?) base.CreateFunc;
set => base.CreateFunc = value;
}

#endregion

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel`1" /> class.
/// </summary>
public InstanceModel() : this(default(Func<Mocker, TClass>)) { }

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.InstanceModel`1" /> class.
/// </summary>
/// <param name="createFunc">The create function.</param>
public InstanceModel(Func<Mocker, TClass>? createFunc) : base(typeof(TClass), typeof(TClass), createFunc) { }

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="InstanceModel{TClass}" /> class.
/// </summary>
/// <param name="createFunc">The create function.</param>
/// <param name="arguments">The arguments.</param>
public InstanceModel(Func<Mocker, TClass>? createFunc, List<object?> arguments) : this(createFunc) =>
Arguments = arguments;

/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:FastMoq.Models.InstanceModel{T}" /> class.
/// </summary>
/// <param name="model">The model.</param>
public InstanceModel(InstanceModel model) : this(model.CreateFunc as Func<Mocker, TClass>, model.Arguments) { }
}
}
8 changes: 4 additions & 4 deletions FastMoq.Tests/InstanceModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,23 @@ public void Create()
[Fact]
public void CreateNullType()
{
Action a = () => _ = new InstanceModel(null) { CreateFunc = _ => new FileSystem() };
Action a = () => _ = new InstanceModel(null, null) { CreateFunc = _ => new FileSystem() };
a.Should().Throw<ArgumentNullException>();

var im = new InstanceModel<IFileSystem>(null);
var im = new InstanceModel<IFileSystem>(default(Func<Mocker, IFileSystem>));
im.InstanceType.Should().Be(typeof(IFileSystem));
im.CreateFunc.Should().BeNull();
}

[Fact]
public void CreateInstance()
{
var obj = new InstanceModel(typeof(IFileSystem), mocker => new FileSystem(), new List<object>());
var obj = new InstanceModel(typeof(IFileSystem), typeof(FileSystem), mocker => new FileSystem(), new List<object>());
obj.Should().NotBeNull();
obj.CreateFunc.Should().NotBeNull();
obj.Arguments.Should().HaveCount(0);

new Action(() => new InstanceModel(typeof(IFileSystem), mocker => new FileSystem(), null)).Should().Throw<ArgumentNullException>();
new Action(() => new InstanceModel(typeof(IFileSystem), typeof(FileSystem), mocker => new FileSystem(), null)).Should().Throw<ArgumentNullException>();
}
}
}
26 changes: 23 additions & 3 deletions FastMoq.Tests/MocksTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ public void Create_WithMapTest1()
o.Should().BeOfType<TestClassDouble1>();
}

[Fact]
public void Create_WithMapTest1b()
{
Mocks.AddType<ITestClassDouble, TestClassDouble1>();
var o = Mocks.CreateInstance<ITestClassDouble>();
o.Should().BeOfType<TestClassDouble1>();
}

[Fact]
public void Create_WithMapTest2()
{
Expand Down Expand Up @@ -365,10 +373,14 @@ public void AddTypeT_ShouldBe_AddType()
{
Mocks.AddType<TestClassOne>(_ => Mocks.CreateInstance<TestClassOne>());
var t = Mocks.typeMap.First().Value.CreateFunc.Invoke(null);
var o = Mocks.CreateInstance<TestClassOne>();
o.Should().BeEquivalentTo(t);
Mocks.typeMap.Clear();
Mocks.AddType(typeof(TestClassOne), typeof(TestClassOne), _=> Mocks.CreateInstance<TestClassOne>());
var t2 = Mocks.typeMap.First().Value.CreateFunc.Invoke(null);
t.Should().BeEquivalentTo(t2);
o = Mocks.CreateInstance<TestClassOne>();
o.Should().BeEquivalentTo(t2);
}

[Fact]
Expand Down Expand Up @@ -605,11 +617,19 @@ public void GetObject_InitAction()
{
var obj = Component.GetObject<TestClass>(t => t.field2 = 3);
obj.field2.Should().Be(3);

Component.AddType<ITestClassDouble, TestClassDouble2>();
var obj2 = Component.GetObject<ITestClassDouble>(t => t.Value = 333.333);
obj2.Value.Should().Be(333.333);
}

[Fact]
public void GetObject_InitAction_ShouldThrowWithoutMap()
{
var obj = Component.GetObject<TestClass>(t => t.field2 = 3);
obj.field2.Should().Be(3);
new Action (() => Component.GetObject<ITestClassDouble>(t => t.Value = 333.333)).Should().Throw<AmbiguousImplementationException>();
}

[Fact]
public void GetObject_ShouldThrow()
{
Expand Down Expand Up @@ -724,14 +744,14 @@ public void Mocker_CreateMockInstanceNull_ShouldThrow() =>
[Fact]
public void Mocker_CreateWithEmptyMap()
{
var test = new Mocker(new Dictionary<Type, InstanceModel>());
var test = new Mocker(new Dictionary<Type, IInstanceModel>());
test.typeMap.Should().BeEmpty();
}

[Fact]
public void Mocker_CreateWithMap()
{
var map = new Dictionary<Type, InstanceModel>
var map = new Dictionary<Type, IInstanceModel>
{
{typeof(IFileSystem), new InstanceModel<IFileSystem>()},
{typeof(IFile), new InstanceModel<IFile>(_ => new MockFileSystem().File)}
Expand Down

0 comments on commit 1e4ead2

Please sign in to comment.