正确设置模拟

时间:2015-08-17 11:39:15

标签: c# moq

我有一个从接口继承的辅助类,它有三个依赖项。

public class StudentHelper : IStudentHelper
{
        private readonly IUpdateStudentManager _updateStudentManager;
        private readonly ISchedulerHelper _schedulerHelper;


        public StudentHelper(
            IUpdateStudentManager updateStudentManager,
            ISchedulerHelper schedulerHelper)
        {
            _updateStudentManager = updateStudentManager;
            _schedulerHelper = schedulerHelper;
        }

        // Rest of the class not shown here for brevity.
}

为了测试这个,我写了一个类似的测试类:

[TestClass]
public class StudentHelperTests
{
    private Mock<StudentHelper> _studentHelperMock;

    private Mock<IUpdateStudentManager> _updateStudentManagerMock;
    private Mock<ISchedulerHelper> _schedulerHelperMock;

    [TestInitialize]
    public void Setup()
    {
        _updateStudentManagerMock = new Mock<IUpdateStudentManager>();
        _schedulerHelperMock = new Mock<ISchedulerHelper>();

        _studentHelperMock = new Mock<StudentHelper>(_updateStudentManagerMock.Object,
            _schedulerHelperMock.Object);
    }

    [TestMethod]
    public void Calling_GetEndDate_Returns_A_FutureDate()
    {
        _productRulesHelper.Setup(x=>x.GetEndDate(DateTime.UtcNow.ToShortDateString(),1)).Returns(DateTime.UtcNow.AddYears(1).ToString("MM/dd/yyyy"));
        _productRulesHelper.VerifyAll();
    }
}

要测试的方法会返回此错误:

  

测试方法StudentHelperTests.Calling_GetEndDate_Returns_A_FutureDate   抛出异常:

     

System.NotSupportedException:非虚拟设置无效   (在VB中可覆盖)成员:x =&gt;   x.GetEndDate(DateTime.UtcNow.ToShortDateString(),1)

GetEndDate方法只接受日期作为字符串,添加一年并将结果日期作为字符串返回。

我认为StudentHelperMock的初始化方式不正确!!!

有人可以指导我吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

您不应该为您尝试测试的实例创建模拟 - 您应该为其依赖项创建模拟

模拟的目的是将被测系统(StudentHelper)与其依赖项(IUpdateStudentManagerISchedulerHelper)隔离,方法是将它们替换为test doubles(例如模拟)

这是您的测试用例应该是什么样的:

[TestMethod]
public void Calling_GetEndDate_Returns_A_FutureDate()
{
    // Arrange
    var helper = new StudentHelper(_updateStudentManagerMock.Object, _schedulerHelperMock.Object);
    var now = DateTime.UtcNow;

    // Act
    var result = x.GetEndDate(now.ToShortDateString(),1);

    // Assert
    Assert.Equal(now.AddYears(1).ToString("MM/dd/yyyy"), result);
}

旁注:我还建议不要使用全局测试设置。请参阅:Why you should not use SetUp and TearDown in NUnit

相关阅读:

答案 1 :(得分:0)

尝试这样的事情:

[TestClass]
public class StudentHelperTests
{
    private StudentHelper _objectToTest;

    private Mock<IUpdateStudentManager> _updateStudentManagerMock;
    private Mock<ISchedulerHelper> _schedulerHelperMock;

    [TestInitialize]
    public void Setup()
    {
        _updateStudentManagerMock = new Mock<IUpdateStudentManager>();
        _schedulerHelperMock = new Mock<ISchedulerHelper>();

        _studentHelperMock = StudentHelper(_updateStudentManagerMock.Object,
            _schedulerHelperMock.Object);
    }

    [TestMethod]
    public void Calling_GetEndDate_Returns_A_FutureDate()
    {
        // The method name says:
       var retrievedDate = _objectToTest.GetEndDate();
       Assert()//... And you should verify than the retrieved date is "a future date" 
    }
}