2015-08-17 48 views
0

我有一個繼承自接口並具有三個依賴關係的助手類。正確設置模擬

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

的方法來測試返回此錯誤:

Test method StudentHelperTests.Calling_GetEndDate_Returns_A_FutureDate threw exception:

System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: x => x.GetEndDate(DateTime.UtcNow.ToShortDateString(), 1)

的GetEndDate方法只需要在一個日期字符串,添加一年並以字符串形式返回結果日期。

我認爲StudentHelperMock初始化的方式是不正確的!

有人能指導我嗎?

在此先感謝。

+0

您還沒有表現出的'定義GetEndDate',但基於錯誤消息,它不是'虛擬'或'抽象'方法。 Moq通過創建你正在嘲笑的事物的動態子類來工作。因此,您可以將它想象爲:如果您可以在子類中覆蓋它,那麼您可以通過Moq模擬它。其他一些模擬框架允許你模擬非虛擬方法。 –

回答

2

你不應該爲你試圖測試的實例創建一個模擬 - 你應該爲它的依賴創建一個模擬

嘲笑的目的是通過用test doubles(例如嘲笑)替代它們的系統下從它的依賴(IUpdateStudentManagerISchedulerHelper)測試(StudentHelper)隔離。

這是你的測試用例應該是什麼樣子:

[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

相關閱讀:

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" 
    } 
}