测试异常的正确方法

本文关键字:方法 异常 测试 | 更新日期: 2023-09-27 18:34:57

我在一个有80%简单逻辑和20%复杂逻辑的项目上做TDD。如果某些方法抛出错误,我发现自己会测试很多,并想知道正确的方法。我使用 NUnit 和 JustMock。

我有两种方法可以做到这一点。使用 ExpectException 属性,并指定类型。或按如下方式编写。写如下的优点是,我也可以断言 exception.message(如果我做了一个自定义的(,如果测试失败,我也会显示 exception.message。但我想和其他人一起检查你是怎么做到的。所以总结一下:

  1. 对这样的异常进行大量测试是否正常?
  2. 这是正确的方法吗:

只是为了解释:供应商提供某些合同,一个部门接受一份合同,但不能与同一供应商签订多份合同(但可以与不同的供应商签订不同的合同(

    [Test]
    public void Accepting_more_than_one_contract_from_supplier_throws_exception()
    {
        //Arrange
        var department = new Department(Guid.NewGuid(), "1234");
        var supplier = Mock.Create<Supplier>();
        var contract1 = Mock.Create<DeliveryContract>();
        var contract2 = Mock.Create<DeliveryContract>();
        var id = Guid.NewGuid();
        supplier.Arrange(x => x.Id).Returns(id);
        contract1.Arrange(x => x.Supplier).Returns(supplier);
        contract2.Arrange(x => x.Supplier).Returns(supplier);
        //Act
        department.AcceptContract(contract1);
        //Assert
        try
        {
            department.AcceptContract(contract2);
            Assert.Fail("Duplicate contract with supplier did not throw an exception");
        }
        catch (Exception ex)
        {   
            Assert.AreEqual(typeof(ArgumentException),ex.GetType(),ex.Message);
        }
    }

测试异常的正确方法

您可以使用 Assert.Throws 方法:

Assert.Throws<ArgumentException>(() => department.AcceptContract(contract2));

Assert.Throws<ArgumentException>(() => department.AcceptContract(contract2), "some message");
正如

@Ufuk所说。使用 T 为异常类型的Assert.Throws<T>

如果您还想检查异常消息,请使用以下方法之一:

T Assert.Throws<T>( TestDelegate code, string message );
T Assert.Throws<T>( TestDelegate code, string message, 
        params object[] parms);

顺便说一下,您为测试创建的数据不应该是模拟数据,而应该是存根。我所说的存根是指仅包含测试数据的对象,在您的情况下,您为对象提供行为 - 而不是数据。

我建议你使用NBuilder code.google.com/p/nbuilder/。您可以通过它创建清晰的存根。它还具有创建对象的极大灵活性,它们可以随机创建或完全为您的测试用例做好准备。

在您的情况下的用法:

var supplierStub = Builder<Supplier>
                .With(supplier => supplier.Id = id)
                .Build();
var contractsStub = Builder<DeliveryContract>.CreateListOfSize(2)
                .All()
                    .With(contract => contract.Supplier = supplierStub)
                .Build();