[英]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.