TL;DR
您应该用以下内容装饰测试方法中的控制器参数[NoAutoProperties]
属性。
[Theory, AutoMoqData]
public void GetWhenHasCustomerTypesShouldReturnOneCustomerType(
IFixture fixture,
[Frozen] Mock<ICustomerTypeService> service,
[NoAutoProperties] CustomerTypeController sut)
{
//Arrange
var items = fixture.CreateMany<Model.CustomerType>(3).ToList();
//Act
var result = sut.Get(1);
//Assert
Assert.IsType<OkResult>(result);
}
Update
现在我对 AutoFixture 代码库有了更好的了解,我想了解为什么这实际上可以解决问题。
The Greedy
属性通常指示 AutoFixture 使用参数最多的构造函数,这应该与修复无关。
正如错误消息所述,当设置属性并且该属性期望实现的值时,会发生异常IModelBinder
。错误的根源是BinderType
的财产BindingInfo
类,其类型System.Type
。默认情况下 AutoFixture 将解析Type
as System.Object
,它解释了错误消息。
当。。。的时候Greedy
应用属性后,这会使用自定义工厂自定义 AutoFixture 以创建属性类型的实例。生成的构建器图节点(可能是意外)会跳过在创建的实例上设置任何属性。
考虑到这一点,更合适的解决方案应该是使用NoAutoProperties
属性。这将显式指示 AutoFixture 忽略修饰类型中的所有自动属性,但会将构造函数查询保留为“适度”。
由于在任何地方添加属性可能会变得烦人且乏味,因此我建议自定义 AutoFixture 以忽略来自的所有属性ControllerBase
,在域定制中。另外,如果您使用属性注入,这将允许 AutoFixture 实例化控制器属性。
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() => new Fixture().Customize(
new CompositeCustomization(
new AutoMoqCustomization(),
new AspNetCustomization())))
{
}
}
public class AspNetCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new ControllerBasePropertyOmitter());
}
}
public class ControllerBasePropertyOmitter : Omitter
{
public ControllerBasePropertyOmitter()
: base(new OrRequestSpecification(GetPropertySpecifications()))
{
}
private static IEnumerable<IRequestSpecification> GetPropertySpecifications()
{
return typeof(ControllerBase).GetProperties().Where(x => x.CanWrite)
.Select(x => new PropertySpecification(x.PropertyType, x.Name));
}
}
如果您需要以下属性ControllerBase
由于某种原因,那么只需指示 AutoFixture 如何正确创建BindingInfo
实例。
原答案
您应该用以下内容装饰测试方法中的控制器参数[Greedy]
属性。
[Theory, AutoMoqData]
public void GetWhenHasCustomerTypesShouldReturnOneCustomerType(
IFixture fixture,
[Frozen] Mock<ICustomerTypeService> service,
[Greedy] CustomerTypeController sut)
{
//Arrange
var items = fixture.CreateMany<Model.CustomerType>(3).ToList();
//Act
var result = sut.Get(1);
//Assert
Assert.IsType<OkResult>(result);
}