簡體   English   中英

Moq:模擬實現IValidatableObject?

[英]Moq: Mocking Implementation of IValidatableObject?

假設我有一個方法希望從IValidatabletableObject的具體實例中提取ValidationResults,並將其粘貼到其他位置...例如,從DTO到控制器的ModelState。

我該如何模擬實現IValidatableObject的對象?

說,我有一些這樣的代碼(尚未編譯):

[Test]
public void GivenBadObjectMethodShouldTransferErrorsToModelstate()
{
  // Mock BadObject and controller
  var controller = new Controller(); 
  var badObject = new Mock<ObjectImplementingIValidatableObject>();
  badObject.Setup( x => x.Validate(It.IsAny<ValidationContext>() )
           .Returns( new List<ValidationResult> { new ValidationResult("error") });

  // Invoke the method
  controller.TransferErrorsToModelStateFrom(badObject);

  // Check that ModelState contains the errors expected
  Assert.IsTrue(controller.ModelState.ContainsKeys("error") );
}

我遇到的一個問題是ValidationContext,出現如下錯誤:System.NotSupportedException:在非虛擬成員上的無效設置x => x.Validate(It.IsAny())

您能否提供一些有關如何更好地解決此問題的見解?

謝謝,

克里斯

您正在嘲笑ObjectImplementingIValidatableObject 具體類型 這可能不是接口,並且其Validate方法被聲明為non-virtual 這是大多數隔離框架(如Moq)無法處理的情況 ,因為它們通過在運行時動態生成模擬類型的子類(或實現)來工作。

如果提供要模擬的接口,則隔離框架會在運行時生成偽造的實現。 如果提供具體類型,則存根/模擬的方法必須是虛擬的,以便框架在動態創建的子類中覆蓋它們。

因此,為了使您的代碼片段正常工作,請考慮使用接口(也許只是IValidatableObject)或將在ObjectImplementingIValidatableObject上聲明的Validate方法設為虛擬。

在進行所有這些操作時,很容易忽略對接口編程的視線。 謝謝你的幫助!

這是我最終得到的代碼:(我已經包含了所有內容,盡管有些部分可以引入設置方法中)

[Test]
    public void GivenValidatableObjectWithMemberErrorThenMethodShouldTransferMemberErrorToModelstate()
    {
        // Setup, getting protected member of abstract class instance
        var controller = (TestConcreteController)FormatterServices
            .GetUninitializedObject(typeof(TestConcreteController));

        MethodInfo ApplyErrorsToModelStateFromModel = controller
            .GetType()
            .GetMethod("ApplyErrorsToModelStateFromModel",
            BindingFlags.Instance | BindingFlags.NonPublic);

        // Setup, building expected objects to pass into method
        IEnumerable<ValidationResult> errors = new List<ValidationResult> 
        { 
            new ValidationResult(TestConstant.ExpectedErrorMessage, TestConstant.ExpectedMembers)
        };

        var objectWithMemberError = new Mock<IValidatableObject>();
        objectWithMemberError.Setup(x => x.Validate(It.IsAny<ValidationContext>()))
                             .Returns(errors);

        // Call the method
        ApplyErrorsToModelStateFromModel.Invoke(controller, new[] { objectWithMemberError.Object });

        // Check that member was added to list and contains the expected error
        Assert.IsTrue(controller.ModelState[TestConstant.ExpectedMembers[0]].Errors[0].ErrorMessage == TestConstant.ExpectedErrorMessage);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM