AutoFixture AutoDataAttribute 单元测试中的 ArgumentNullException
ArgumentNullException in a unit test for AutoFixture AutoDataAttribute
我正在为 related SO question 编写 ApiControllerConventions
的单元测试,我编写了 AutoMoqApiControllerDataAttribute
以将此 ICustomization
集成到 xUnit.net 中。
public class AutoMoqApiControllerDataAttribute : AutoDataAttribute
{
public AutoMoqApiControllerDataAttribute() : this(new Fixture())
{
}
public AutoMoqApiControllerDataAttribute(IFixture fixture) : base(
fixture.Customize(new ApiControllerConventions()))
{
}
}
我试过像这样为此属性编写单元测试:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : this(new Fixture())
{
}
public AutoMoqDataAttribute(IFixture fixture) :
base(fixture.Customize(new AutoMoqCustomization()))
{
}
}
[Theory, AutoMoqData]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization(
Mock<IFixture> mockFixture)
{
// Arrange
mockFixture.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>())).Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(f => f.Customize(It.IsAny<ApiControllerConventions>()), Times.Once);
}
失败,异常来自 AutoDataAttribute
:
System.ArgumentNullException
Value cannot be null.
Parameter name: fixture
at Ploeh.AutoFixture.Xunit2.AutoDataAttribute..ctor(IFixture fixture)
我认为这与我对 AutoMoqDataAttribute
的使用有关,所以我恢复到原版 Fact
,同样的异常仍然存在:
[Fact]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
{
// Arrange
var mockFixture = new Mock<IFixture>();
mockFixture.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>())).Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(f => f.Customize(It.IsAny<ApiControllerConventions>()), Times.Once);
}
为什么我得到异常?我显然嘲笑了 IFixture
并且它绝对不是空的。
当您遇到异常时,查看调用堆栈总是一个好主意。异常不是在 AutoMoqApiControllerDataAttribute
中抛出,而是在 AutoDataAttribute
:
中抛出
System.ArgumentNullException : Value cannot be null.
Parameter name: fixture
at Ploeh.AutoFixture.Xunit2.AutoDataAttribute..ctor(IFixture fixture)
AutoMoqApiControllerDataAttribute.cs(12,0): at _44380395.AutoMoqApiControllerDataAttribute..ctor(IFixture fixture)
Tests.cs(22,0): at _44380395.Tests.AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
虽然 fixture
在传递给 AutoMoqApiControllerDataAttribute
时不是 null
,但在传递给 时 null
=19=].
为什么?
考虑对 base
的调用:
base(fixture.Customize(new ApiControllerConventions()))
哪个值正在传递给 base
?
不是 fixture
,而是调用 fixture.Customize
.
的 return 值
测试没有为此方法调用设置 return 值,因此 Moq 默认为该类型的默认值。由于 IFixture
是引用类型,这意味着 null
,然后 null
值将传递给 base
.
您可以通过在测试中使用 return 值配置 mockFixture
轻松解决问题:
[Fact]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
{
// Arrange
var mockFixture = new Mock<IFixture>();
mockFixture
.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>()))
.Returns(mockFixture.Object)
.Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(
f => f.Customize(It.IsAny<ApiControllerConventions>()),
Times.Once());
}
现在我的测试通过了。
这不是 AutoFixture 特有的问题。您可以使用任何 Fluent Interface.
重现它
我正在为 related SO question 编写 ApiControllerConventions
的单元测试,我编写了 AutoMoqApiControllerDataAttribute
以将此 ICustomization
集成到 xUnit.net 中。
public class AutoMoqApiControllerDataAttribute : AutoDataAttribute
{
public AutoMoqApiControllerDataAttribute() : this(new Fixture())
{
}
public AutoMoqApiControllerDataAttribute(IFixture fixture) : base(
fixture.Customize(new ApiControllerConventions()))
{
}
}
我试过像这样为此属性编写单元测试:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : this(new Fixture())
{
}
public AutoMoqDataAttribute(IFixture fixture) :
base(fixture.Customize(new AutoMoqCustomization()))
{
}
}
[Theory, AutoMoqData]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization(
Mock<IFixture> mockFixture)
{
// Arrange
mockFixture.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>())).Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(f => f.Customize(It.IsAny<ApiControllerConventions>()), Times.Once);
}
失败,异常来自 AutoDataAttribute
:
System.ArgumentNullException Value cannot be null. Parameter name: fixture at Ploeh.AutoFixture.Xunit2.AutoDataAttribute..ctor(IFixture fixture)
我认为这与我对 AutoMoqDataAttribute
的使用有关,所以我恢复到原版 Fact
,同样的异常仍然存在:
[Fact]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
{
// Arrange
var mockFixture = new Mock<IFixture>();
mockFixture.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>())).Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(f => f.Customize(It.IsAny<ApiControllerConventions>()), Times.Once);
}
为什么我得到异常?我显然嘲笑了 IFixture
并且它绝对不是空的。
当您遇到异常时,查看调用堆栈总是一个好主意。异常不是在 AutoMoqApiControllerDataAttribute
中抛出,而是在 AutoDataAttribute
:
System.ArgumentNullException : Value cannot be null.
Parameter name: fixture
at Ploeh.AutoFixture.Xunit2.AutoDataAttribute..ctor(IFixture fixture)
AutoMoqApiControllerDataAttribute.cs(12,0): at _44380395.AutoMoqApiControllerDataAttribute..ctor(IFixture fixture)
Tests.cs(22,0): at _44380395.Tests.AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
虽然 fixture
在传递给 AutoMoqApiControllerDataAttribute
时不是 null
,但在传递给 时 null
=19=].
为什么?
考虑对 base
的调用:
base(fixture.Customize(new ApiControllerConventions()))
哪个值正在传递给 base
?
不是 fixture
,而是调用 fixture.Customize
.
测试没有为此方法调用设置 return 值,因此 Moq 默认为该类型的默认值。由于 IFixture
是引用类型,这意味着 null
,然后 null
值将传递给 base
.
您可以通过在测试中使用 return 值配置 mockFixture
轻松解决问题:
[Fact]
public void AutoMoqApiControllerDataAttribute_ContainsCorrectCustomization()
{
// Arrange
var mockFixture = new Mock<IFixture>();
mockFixture
.Setup(f => f.Customize(It.IsAny<ApiControllerConventions>()))
.Returns(mockFixture.Object)
.Verifiable();
// Act
var sut = new AutoMoqApiControllerDataAttribute(mockFixture.Object);
// Assert
mockFixture.Verify(
f => f.Customize(It.IsAny<ApiControllerConventions>()),
Times.Once());
}
现在我的测试通过了。
这不是 AutoFixture 特有的问题。您可以使用任何 Fluent Interface.
重现它