简体   繁体   English

如何处理NUnit中的抛出异常

[英]How to handle thrown exception in NUnit

I have written a unit test class in C# for my MVC project. 我已经在C#中为我的MVC项目编写了一个单元测试类。

The Test Method is following 测试方法如下

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

And the Service Method is following 服务方法如下

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

Now This test method only not passed due to the service class thrown ArgumentNullException.So how to handle the ArgumentNullException or How to make this test pass? 现在这个测试方法只是因为服务类抛出而没有传递ArgumentNullException.So如何处理ArgumentNullException或如何让这个测试通过?

Please anybody help 请任何人帮忙

If you are trying to check that the ArgumentNullException is working (which: it isn't currently). 如果您正在尝试检查ArgumentNullException是否正常工作(其中:它当前不是)。 then it sounds like you want: 那听起来像你想要的:

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

I am assuming: Looking at the code this unit test should not pass. 我假设:看看代码,这个单元测试不应该通过。 Adding a NULL to a list is in most cases not an intended behaviour. 在大多数情况下,向列表添加NULL不是预期的行为。

I see 2 options: A) You should add a try/catch to you Test metod. 我看到两个选项:A)你应该为你测试metod添加一个try / catch。

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

B) Remove the try/catch block from the Test Method so you do not swallow the exception. B)从测试方法中删除try / catch块,这样就不会吞下异常。 (Every Test that does not fails or an Assert or thows an unhandeled exception automatically passes) (每个没有失败的测试或者Assert或者unhandeled异常会自动通过)

Testing for the ArgumentNullException 测试ArgumentNullException

If you remove the ill-advised 如果你删除了不明智的

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

from your code to be tested (The current catch loses context of the error, and breaks the stack trace, see below), your test can be as simple as wrapping the invocation in an Assert.Throws<ArgumentNullException>() : 从您要测试的代码(当前catch失去错误的上下文,并打破堆栈跟踪,见下文),您的测试可以像在Assert.Throws<ArgumentNullException>()包装调用一样简单Assert.Throws<ArgumentNullException>()

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

Re: Your Exception Handler Re:你的异常处理程序

In your service code, never catch an exception and rethrow it as you've done, as this will lose the stack trace (eg _repository.Add(entity); could throw as well.). 在您的服务代码中,永远不会捕获异常并重新抛出它,因为这将丢失堆栈跟踪(例如_repository.Add(entity);也可以抛出。)。 You also aren't adding any value by throwing e.Message as this is already in the original exception (with additional info like stack trace and inner exception) 您也没有通过抛出e.Message来添加任何值,因为它已经在原始异常中(包含堆栈跟踪和内部异常等附加信息)

Bad: 坏:

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

Better: If you do catch and rethrow with some value, wrap the original as an inner exception: 更好:如果您捕获并重新抛出某些值,请将原始内容包装为内部异常:

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

or if you are just intercepting and allow to propagate: 或者如果你只是拦截并允许传播:

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

Best to me would to let the exception propagate, unless you either adding value, or handling it. 除非您添加值或处理它,否则我最好让异常传播。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM