11

我有以下课程和测试。我想测试将 null 值作为参数传递给构造函数,并期待ArgumentNullException. 但是因为我使用了 Autofixture 的CreateAnonymous方法,所以我得到了一个TargetInvocationException

编写这些测试的正确方法是什么?

public sealed class CreateObject : Command {
    // Properties
    public ObjectId[] Ids { get; private set; }
    public ObjectTypeId ObjectType { get; private set; }
    public UserId CreatedBy { get; private set; }

    // Constructor
    public CreateObject(ObjectId[] ids, ObjectTypeId objectType, UserId createdBy) {
      Guard.NotNull(ids, "ids");
      Guard.NotNull(objectType, "objectType");
      Guard.NotNull(createdBy, "createdBy");

      Ids = ids;
      ObjectType = objectType;
      CreatedBy = createdBy;
    }
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void constructor_with_null_ids_throw() {
    fixture.Register<ObjectId[]>(() => null);
    fixture.CreateAnonymous<CreateObject>();
}
4

2 回答 2

13

IMO,Ruben Bartelink 的评论是最好的答案。

使用AutoFixture.Idioms,您可以这样做:

var fixture = new Fixture();
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(CreateObject).GetConstructors());

如果任何构造函数中的任何构造函数参数缺少保护子句,Verify 方法将为您提供非常详细的异常消息。


FWIW,AutoFixture 广泛使用反射,所以我不认为它抛出一个错误TargetInvocationException。虽然它可以解开所有TargetInvocationException实例并重新抛出它们的InnerException属性,但这也意味着处理(可能)有价值的信息(例如 AutoFixture 堆栈跟踪)。我已经考虑过这一点,但出于这个原因,我不想将 AutoFixture 朝那个方向发展。客户端总是可以过滤掉信息,但是如果信息被过早地删除,客户端就无法取回它。

如果您更喜欢另一种方法,那么编写一个解开异常的辅助方法并不难 - 可能是这样的:

public Exception Unwrap(this Exception e)
{
    var tie = e as TargetInvocationException;
    if (tie != null)
        return tie.InnerException;
    return e;
}
于 2013-02-26T07:05:27.167 回答
0

我在寻找类似的东西时遇到了这个。我想补充一点,结合 automoqcustomization 和 xunit,下面的代码也可以工作,而且更简洁。

    [Theory, AutoMoqData]
    public void Constructor_GuardClausesArePresent(GuardClauseAssertion assertion)
    {
        assertion.Verify(typeof(foo).GetConstructors());
    }

您只需按如下方式创建 AutoMoqData 属性。

    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new AutoMoqCustomization()))
        {

        }
    }
于 2018-01-06T12:00:20.480 回答