自动 return 来自模拟泛型函数的夹具值?
Automatically return fixture values from mocked generic functions?
我的测试使用 Moq 和 AutoFixture,它们通常非常冗长,因为它们有许多模拟 Setup() 调用来将模拟配置为由 AutoFixture 创建的 return 值。为了使测试更易于阅读和维护,我尝试将 AutoMoqCustomization 与 ConfigureMembers 功能结合使用,以避免不必要的 Setup() 调用。
大多数情况下这是按预期工作的,但是我有一些接口具有 AutoMoqCustomization 似乎无法处理的通用函数(主要是 AutoMapper)。我没有从 AutoFixture returning 一个类型的实例,而是收到一个模拟实例。
我可以通过包含对通用函数的 Setup() 调用来实现我想要的行为,但我的目标是尽可能多地删除这些 Setup 调用。
我已经设置了下面的示例来重现问题(实际上我使用 AutoFixture 通过另一个对象的构造函数注入 IMapper 实例,并且该对象调用了 IMapper 接口,但事实并非如此有必要查看有问题的行为)。
我希望对 sut.Map<object>()
的调用能够像对 sut.Map()
的调用一样工作,return 冻结固定装置中的 object
实例。相反,在变量 retB
中,我看到了 ObjectProxy
.
的一个实例
在为 Map<object>()
设置 return 值的示例中包含注释行将导致测试通过,但我更愿意以与我相同的方式省略此调用省略 Map()
.
的 Setup() 调用
是否应该自动配置通用函数?我设置不正确吗?
using AutoFixture;
using AutoFixture.AutoMoq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace UnitTestProject1
{
public interface IMapper
{
object Map();
object Map<T>();
}
[TestClass]
public class Tests
{
[TestMethod]
public void Test()
{
var f = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
var model = f.Freeze<object>();
var sut = f.Create<IMapper>();
//Mock.Get(sut).Setup(x => x.Map<object>()).ReturnsUsingFixture(f);
var retA = sut.Map();
var retB = sut.Map<object>();
Assert.AreEqual(model, retA);
Assert.AreEqual(model, retB); }
}
}
事实上,autofixture 中的 AutoMoq 自定义目前不支持通用方法,因为它的编写方式受到限制,但是有一个 issue/PR 可以集成它:
https://github.com/AutoFixture/AutoFixture/issues/1139
据我所知,它还没有合并,因为它会引入更高的 Moq 依赖版本。它利用 Moq 引入的 relatively-recently DefaultValueProvider
属性 将所有 'default value' 职责委托给 AutoFixture,而不是让 Moq 递归地引入模拟对象。听起来正是您想要的。
从这个问题来看,这里有一个示例,说明如果您要引入与 the pull request 引入的定制类似的定制,它会是什么样子:
var fixture = new Fixture();
fixture.Customize<string>(x => x.FromSeed(y => "asf"));
var mock = new Mock<IInterfaceWithGenericMethod>
{
DefaultValueProvider = new AutoFixtureValueProvider(fixture)
};
Assert.Equal("asf", mock.Object.GenericMethod<string>());
我的测试使用 Moq 和 AutoFixture,它们通常非常冗长,因为它们有许多模拟 Setup() 调用来将模拟配置为由 AutoFixture 创建的 return 值。为了使测试更易于阅读和维护,我尝试将 AutoMoqCustomization 与 ConfigureMembers 功能结合使用,以避免不必要的 Setup() 调用。
大多数情况下这是按预期工作的,但是我有一些接口具有 AutoMoqCustomization 似乎无法处理的通用函数(主要是 AutoMapper)。我没有从 AutoFixture returning 一个类型的实例,而是收到一个模拟实例。
我可以通过包含对通用函数的 Setup() 调用来实现我想要的行为,但我的目标是尽可能多地删除这些 Setup 调用。
我已经设置了下面的示例来重现问题(实际上我使用 AutoFixture 通过另一个对象的构造函数注入 IMapper 实例,并且该对象调用了 IMapper 接口,但事实并非如此有必要查看有问题的行为)。
我希望对 sut.Map<object>()
的调用能够像对 sut.Map()
的调用一样工作,return 冻结固定装置中的 object
实例。相反,在变量 retB
中,我看到了 ObjectProxy
.
在为 Map<object>()
设置 return 值的示例中包含注释行将导致测试通过,但我更愿意以与我相同的方式省略此调用省略 Map()
.
是否应该自动配置通用函数?我设置不正确吗?
using AutoFixture;
using AutoFixture.AutoMoq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace UnitTestProject1
{
public interface IMapper
{
object Map();
object Map<T>();
}
[TestClass]
public class Tests
{
[TestMethod]
public void Test()
{
var f = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
var model = f.Freeze<object>();
var sut = f.Create<IMapper>();
//Mock.Get(sut).Setup(x => x.Map<object>()).ReturnsUsingFixture(f);
var retA = sut.Map();
var retB = sut.Map<object>();
Assert.AreEqual(model, retA);
Assert.AreEqual(model, retB); }
}
}
事实上,autofixture 中的 AutoMoq 自定义目前不支持通用方法,因为它的编写方式受到限制,但是有一个 issue/PR 可以集成它: https://github.com/AutoFixture/AutoFixture/issues/1139
据我所知,它还没有合并,因为它会引入更高的 Moq 依赖版本。它利用 Moq 引入的 relatively-recently DefaultValueProvider
属性 将所有 'default value' 职责委托给 AutoFixture,而不是让 Moq 递归地引入模拟对象。听起来正是您想要的。
从这个问题来看,这里有一个示例,说明如果您要引入与 the pull request 引入的定制类似的定制,它会是什么样子:
var fixture = new Fixture();
fixture.Customize<string>(x => x.FromSeed(y => "asf"));
var mock = new Mock<IInterfaceWithGenericMethod>
{
DefaultValueProvider = new AutoFixtureValueProvider(fixture)
};
Assert.Equal("asf", mock.Object.GenericMethod<string>());