15

想要对以下类中的方法进行单元测试

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

}

笔记:

  • 方法名称 = AuthoriseDeviceProfile 返回 void
  • 该方法检查 userSentMakeModel 与存储在 db 匹配中的那个
  • 如果匹配 - 它只是返回(即不改变任何状态)

我们将如何对这个方法进行单元测试?

  • 嘲笑了回购
  • 涵盖了“抛出异常”的场景
  • 问题是如何对 ALL WENT WELL 的场景进行单元测试,即用户;s makeModel 与存储库匹配;s makeModel

非常欢迎任何使此可测试的设计建议提前谢谢。

4

6 回答 6

15

由于您的方法返回 void,它可能具有一些您可以测试/断言的副作用。

在您的情况下,一个选项是提供IDeviceAuthorisationRepositioryService. 然后,您可以检查是否UpdatePhoneStatusToActive发生了呼叫。这是使用Moq的解决方案:

var mock = new Mock<IDeviceAuthorisationRepositioryService>();

var service = new DeviceAuthorisationService(mock.Object);
service.UpdateDeviceStatusToActive(....);

mock.Verify(x => service.UpdatePhoneStatusToActive(), Times.Never());
于 2012-12-11T12:57:47.550 回答
7

如果一个方法是无效的,那么它应该有一些可观察到的副作用——否则它是没有意义的。因此,您无需测试返回值,而是测试副作用。在这种情况下,看起来可能是在哪些情况下引发了哪些异常。

(在这里,“抛出异常”被认为是一种副作用;您当然也可以将其视为一种隐式的返回值......)

于 2012-12-11T12:53:59.997 回答
5

注入一个模拟存储库。测试是否调用了存储库上的某些方法。

于 2012-12-11T12:55:20.653 回答
3

您可以在单元测试中设置异常预期。在 nUnit 中,它看起来像这样:

[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void TestAuthoriseFail()
{
    // do something that should make the tested method throw the exception
}
于 2012-12-11T12:55:07.870 回答
2

即使您的方法返回 void,它也必须做一些对您有用的事情(否则它将是一个毫无意义的方法)。

从您的代码中,我猜该AuthoriseDeviceProfile方法正在做的基本上有两种“有用”的东西:

  • 调用上的GetSelectedPhoneDetails方法IDeviceAuthorisationRepositiory
  • 根据特定条件抛出各种异常

因此,要对该方法进行单元测试,您应该执行与此相对应的两件事:

  • 注入一个模拟IDeviceAuthorisationRepositiory并让它记录和/或断言是否GetSelectedPhoneDetails被调用
  • 练习引发各种异常的测试方法,并在它们被抛出时捕获它们以验证:
    • 实际上抛出了一个异常
    • 引发的异常适用于每种情况
于 2012-12-11T13:05:32.380 回答
0
  [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);
            }
        }
    }
于 2018-05-14T12:50:35.950 回答