C# 单元测试返回空值的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13820809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit Test a method that returns a void
提问by Venu b
Wanted to Unit Test a method in the following Class
想要对以下类中的方法进行单元测试
public class DeviceAuthorisationService : IDeviceAuthorisationService
{
private DeviceDetailsDTO deviceDetailsDTO = null;
private IDeviceAuthorisationRepositiory deviceAuthorisationRepositiory;
public DeviceAuthorisationService(IDeviceAuthorisationRepositioryService paramDeviceAuthorisationRepository)
{
deviceAuthorisationRepositiory = paramDeviceAuthorisationRepository;
}
public void AuthoriseDeviceProfile(long paramUserID, string paramClientMakeModel)
{
if (deviceDetailsDTO == null)
GetCellPhoneDetails(userID);
if (deviceDetailsDTO.IsDeviceSelected == false)
throw new SomeCustomExceptionA();
if (deviceDetailsDTO.CellPhoneMakeModel.ToLower() != paramClientMakeModel.ToLower())
throw new SomeCustomExceptionB;
}
public void UpdateDeviceStatusToActive(long userID)
{
if (deviceDetailsDTO == null)
throw new InvalidOperationException("UnAuthorised Device Profile Found Exception");
if (deviceDetailsDTO.PhoneStatus != (short)Status.Active.GetHashCode())
deviceAuthorisationRepositiory.UpdatePhoneStatusToActive(deviceDetailsDTO.DeviceID);
}
private void GetCellPhoneDetails(long userID)
{
deviceDetailsDTO = deviceAuthorisationRepositiory.GetSelectedPhoneDetails(userID);
if (deviceDetailsDTO == null)
throw new SomeCustomException()
}
}
Note:
笔记:
- Method Name = AuthoriseDeviceProfile returns void
- The method checks userSentMakeModel against the one stored in the db match
- If it matches - it simply returns (ie does not change any state)
- 方法名称 = AuthoriseDeviceProfile 返回 void
- 该方法检查 userSentMakeModel 与存储在数据库匹配中的那个
- 如果匹配 - 它只是返回(即不改变任何状态)
How will we unit test this method?
我们将如何对这个方法进行单元测试?
- Have mocked the Repo
- Have covered scenario of "THROWS EXCEPTION"
- Question is how to unit test the scenario of ALL WENT WELL ie user;s makeModel matched with repository;s makeModel
- 嘲笑了回购协议
- 已经涵盖了“抛出异常”的场景
- 问题是如何对 ALL WENT WELL 的场景进行单元测试,即 user;s makeModel 与 repository;s makeModel 匹配
Any design suggestions to make this testable is most welcome Thanks in advance.
任何使此可测试的设计建议都非常受欢迎 提前致谢。
采纳答案by alexn
Since your method returns void, it probably has some side-effect that you can test/assert on.
由于您的方法返回 void,因此它可能具有一些您可以测试/断言的副作用。
In your case, an option would be to provide a mock instance of IDeviceAuthorisationRepositioryService. You can then check if a call to UpdatePhoneStatusToActivehas happened. Here is a solution using Moq:
在您的情况下,一个选项是提供IDeviceAuthorisationRepositioryService. 然后,您可以检查是否UpdatePhoneStatusToActive发生了呼叫。这是使用Moq的解决方案:
var mock = new Mock<IDeviceAuthorisationRepositioryService>();
var service = new DeviceAuthorisationService(mock.Object);
service.UpdateDeviceStatusToActive(....);
mock.Verify(x => service.UpdatePhoneStatusToActive(), Times.Never());
回答by Jon Skeet
If a method is void, then it should have some observable side-effect - otherwise it's pointless. So instead of testing the return value, you test the side-effects. In this case, it looks like those a probably around which exceptions are thrown in which situations.
如果一个方法是无效的,那么它应该有一些可观察到的副作用 - 否则它毫无意义。因此,您不是测试返回值,而是测试副作用。在这种情况下,看起来像是在哪些情况下可能会抛出异常。
(Here, "throws an exception" is deemed a side-effect; you could also think of it as an implicit kind of return value of course...)
(在这里,“抛出异常”被认为是一种副作用;当然,您也可以将其视为一种隐式的返回值......)
回答by Phil Gan
You can set exception expectancies on your unit tests. In nUnit it looks like this:
您可以在单元测试中设置异常预期。在 nUnit 中,它看起来像这样:
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void TestAuthoriseFail()
{
// do something that should make the tested method throw the exception
}
回答by Zdravko Danev
Inject a mocked repository. Test if certain methods on the repository are called.
注入模拟存储库。测试是否调用了存储库上的某些方法。
回答by Chamila Chulatunga
Even if your method returns void, it must be doing something that is useful for you (otherwise it would be a pointless method to have).
即使您的方法返回 void,它也必须做一些对您有用的事情(否则它将是一个毫无意义的方法)。
From your code, I'm guessing there are essentially 2 flavours of 'useful' things that the AuthoriseDeviceProfilemethod is doing:
从您的代码中,我猜测该方法基本上有两种“有用”的东西AuthoriseDeviceProfile:
- calling the
GetSelectedPhoneDetailsmethod on theIDeviceAuthorisationRepositiory - throwing various exceptions based on certain conditions
- 调用
GetSelectedPhoneDetails方法IDeviceAuthorisationRepositiory - 根据特定条件抛出各种异常
Therefore to unit test the method, you should do two things that correspond to this:
因此,要对该方法进行单元测试,您应该做两件与此相对应的事情:
- Inject a mock
IDeviceAuthorisationRepositioryand have it record and/or assert whetherGetSelectedPhoneDetailsis called - Exercise test methods that induce the various exceptions, and capture them as they are thrown to verify that:
- an exception is in fact thrown
- the exception that is thrown is the appropriate one for each scenario
- 注入一个模拟
IDeviceAuthorisationRepositiory并让它记录和/或断言是否GetSelectedPhoneDetails被调用 - 练习引发各种异常的测试方法,并在抛出它们时捕获它们以验证:
- 实际上抛出了一个异常
- 抛出的异常是适合每个场景的异常
回答by Lijo
[TestMethod]
public void AuthoriseDeviceProfileTest()
{
long paramUserID=1, string paramClientMakeModel=test";
IDeviceAuthorisationService DeviceAuthorisationService= new DeviceAuthorisationService();
try
{
DeviceAuthorisationService.AuthoriseDeviceProfile(paramUserID, paramClientMakeModel);
Assert.IsNull(paramUserID);
}
catch (Exception e)
{
Assert.AreNotEqual("Exception of type was thrown", e.Message);
}
}
}

