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
请任何人帮忙
3 个解决方案
#1
5
If you are trying to check that the ArgumentNullException
is working (which: it isn't currently). then it sounds like you want:
如果您正在尝试检查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);
}
#2
1
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.
我看到2个选项: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. (Every Test that does not fails or an Assert or thows an unhandeled exception automatically passes)
B)从测试方法中删除try / catch块,这样就不会吞下异常。 (每个没有失败的测试或者Assert或者unhandeled异常会自动通过)
#3
-1
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
[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 (e.g. _repository.Add(entity);
could throw as well.). 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)
在您的服务代码中,永远不会捕获异常并重新抛出它,因为这将丢失堆栈跟踪(例如_repository.Add(entity);也可以抛出。)。您也没有通过抛出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.
除非您添加值或处理它,否则我最好让异常传播。
#1
5
If you are trying to check that the ArgumentNullException
is working (which: it isn't currently). then it sounds like you want:
如果您正在尝试检查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);
}
#2
1
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.
我看到2个选项: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. (Every Test that does not fails or an Assert or thows an unhandeled exception automatically passes)
B)从测试方法中删除try / catch块,这样就不会吞下异常。 (每个没有失败的测试或者Assert或者unhandeled异常会自动通过)
#3
-1
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
[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 (e.g. _repository.Add(entity);
could throw as well.). 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)
在您的服务代码中,永远不会捕获异常并重新抛出它,因为这将丢失堆栈跟踪(例如_repository.Add(entity);也可以抛出。)。您也没有通过抛出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.
除非您添加值或处理它,否则我最好让异常传播。