如何在NUnit中处理抛出的异常

本文关键字:异常 处理 NUnit | 更新日期: 2023-09-27 18:24:53

我用C#为我的MVC项目编写了一个单元测试类。

测试方法遵循

 [Test]
    public void To_Add_DocumentStatusIsNull_ThrowsInvalidOperationException_ServiceTest()
    {
        try
        {
        _IDocumentStatusRepositoryMock = new Mock<IDocumentStatusRepository>();
        _unitOfWorkMock = new Mock<IUnitOfWork>();
        DocumentStatusService documentStatusService = new  
         DocumentStatusService(_unitOfWorkMock.Object,  
          _IDocumentStatusRepositoryMock.Object); 
        DocumentStatus documentStatus;
        documentStatus = null;
        _IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
        documentStatusService.Add(documentStatus);
        Assert.Pass();
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }

服务方法遵循

   public virtual void Add(TEntity entity)
    {
        try
        {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }
        _repository.Add(entity);
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }

现在这个测试方法由于服务类抛出了ArgumentNullException而没有通过。那么如何处理ArgumentNullException或者如何使这个测试通过呢?

请任何人帮助

如何在NUnit中处理抛出的异常

如果您正在尝试检查ArgumentNullException是否工作(当前不工作)。然后听起来你想要:

[Test, ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: entity")]
public void To_Add_DocumentStatusIsNull_ThrowsInvalidOperationException_ServiceTest()
{
    _IDocumentStatusRepositoryMock = new Mock<IDocumentStatusRepository>();
    _unitOfWorkMock = new Mock<IUnitOfWork>();
    DocumentStatusService documentStatusService = new  
     DocumentStatusService(_unitOfWorkMock.Object,  
      _IDocumentStatusRepositoryMock.Object); 
    DocumentStatus documentStatus;
    documentStatus = null;
    _IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
    documentStatusService.Add(documentStatus);
}

public virtual void Add(TEntity entity)
{
    if (entity == null)
    {
        throw new ArgumentNullException("entity");
    }
    _repository.Add(entity);
}

ArgumentNullException测试

如果您删除了不明智的

catch (Exception e)
{
   throw new Exception(e.Message);
}

从要测试的代码中(当前的catch丢失了错误的上下文,并中断了堆栈跟踪,请参见下文),您的测试可以像将调用封装在Assert.Throws<ArgumentNullException>():中一样简单

[Test]
public void PassingANullEntityToAddMustThrowArgumentNullException()
{
    var documentStatusService = new  DocumentStatusService(...); 
    Assert.Throws<ArgumentNullException>(() =>  documentStatusService.Add(null));
}

回复:您的异常处理程序

在您的服务代码中,永远不要像您所做的那样捕获异常并重新抛出它,因为这将丢失堆栈跟踪(例如,_repository.Add(entity);也可能抛出。)。您也不会通过抛出e.Message来添加任何值,因为这已经在原始异常中了(包括堆栈跟踪和内部异常等附加信息)

错误:

  catch (Exception e)
  {
      throw new Exception(e.Message);
  }

更好:如果您确实捕获并重新抛出了一些值,那么将原始值包装为内部异常:

 catch (SqlException ex)
 {
    throw new Exception("Some value add here", ex);
 }

或者如果你只是拦截并允许传播:

 catch (SqlException)
 {
    // Do some logging
    throw;
 }

对我来说,最好是让异常传播,除非你增加值或处理它。

我假设:看看这个单元测试不应该通过的代码。在大多数情况下,向列表中添加NULL不是一种预期行为。

我看到两个选项:A) 你应该在你的测试方法中添加一个try/catch。

try 
{
    _IDocumentStatusRepositoryMock.Setup(m => m.Add(documentStatus));
    documentStatusService.Add(documentStatus);
}
catch (Exception )
{
    Assert.Fail(); // or nothing is expected behaviour
}

B) 从测试方法中删除try/catch块,这样就不会吞下异常。(每个没有失败的测试、断言或引发未处理异常的测试都会自动通过)