正确的例外测试方法

时间:2013-10-12 08:37:35

标签: c# unit-testing tdd nunit domain-driven-design

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

我有两种方法可以做到这一点。使用ExpectedException属性,并指定类型。或写作如下。写下面的专业人员是我也可以断言exception.message(如果我已经制作了一个自定义的),如果测试失败,我也会显示exception.message。但是我想和别人一起检查你是怎么做的。总结一下:

  1. 对此类例外进行大量测试是否正常?
  2. 这是正确的方法:
  3.   

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

        [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);
            }
        }
    

2 个答案:

答案 0 :(得分:6)

您可以使用Assert.Throws方法:

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

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

答案 1 :(得分:2)

正如@Ufuk所说。使用Assert.Throws<T>,其中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();