Saya memeriksa ModelState.IsValid
dalam metode tindakan pengontrol saya yang membuat Karyawan seperti ini:
[HttpPost]
public virtual ActionResult Create(EmployeeForm employeeForm)
{
if (this.ModelState.IsValid)
{
IEmployee employee = this._uiFactoryInstance.Map(employeeForm);
employee.Save();
}
// Etc.
}
Saya ingin mengejeknya dalam metode pengujian unit saya menggunakan Moq Framework. Saya mencoba mengejeknya seperti ini:
var modelState = new Mock<ModelStateDictionary>();
modelState.Setup(m => m.IsValid).Returns(true);
Tapi ini menimbulkan pengecualian dalam kasus uji unit saya. Adakah yang bisa membantu saya di sini?
c#
asp.net-mvc
unit-testing
mocking
moq
Mazen
sumber
sumber
Satu-satunya masalah yang saya miliki dengan solusi di atas adalah bahwa itu tidak benar-benar menguji model jika saya menetapkan atribut. Saya mengatur pengontrol saya dengan cara ini.
private HomeController GenerateController(object model) { HomeController controller = new HomeController() { RoleService = new MockRoleService(), MembershipService = new MockMembershipService() }; MvcMockHelpers.SetFakeAuthenticatedControllerContext(controller); // bind errors modelstate to the controller var modelBinder = new ModelBindingContext() { ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()), ValueProvider = new NameValueCollectionValueProvider(new NameValueCollection(), CultureInfo.InvariantCulture) }; var binder = new DefaultModelBinder().BindModel(new ControllerContext(), modelBinder); controller.ModelState.Clear(); controller.ModelState.Merge(modelBinder.ModelState); return controller; }
Objek modelBinder adalah objek yang menguji validitas model. Dengan cara ini saya bisa mengatur nilai objek dan mengujinya.
sumber
Jawaban uadrive membantu saya, tetapi masih ada beberapa celah. Tanpa data apa pun di input ke
new NameValueCollectionValueProvider()
, pengikat model akan mengikat pengontrol ke model kosong, bukan kemodel
objek.Tidak apa-apa - cukup buat model Anda
NameValueCollection
menjadi serial, lalu teruskan keNameValueCollectionValueProvider
konstruktor. Yah, kurang tepat. Sayangnya, ini tidak berfungsi dalam kasus saya karena model saya berisi koleksi, dan tidak berfungsiNameValueCollectionValueProvider
dengan baik dengan koleksi.Tapi
JsonValueProviderFactory
datang untuk menyelamatkannya di sini. Ini dapat digunakanDefaultModelBinder
selama Anda menentukan jenis konten"application/json
"dan meneruskan objek JSON serial Anda ke dalam aliran input permintaan Anda (Harap diperhatikan, karena aliran input ini adalah aliran memori, tidak apa-apa membiarkannya tidak dibuang, sebagai memori aliran tidak berpegang pada sumber daya eksternal):protected void BindModel<TModel>(Controller controller, TModel viewModel) { var controllerContext = SetUpControllerContext(controller, viewModel); var bindingContext = new ModelBindingContext { ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => viewModel, typeof(TModel)), ValueProvider = new JsonValueProviderFactory().GetValueProvider(controllerContext) }; new DefaultModelBinder().BindModel(controller.ControllerContext, bindingContext); controller.ModelState.Clear(); controller.ModelState.Merge(bindingContext.ModelState); } private static ControllerContext SetUpControllerContext<TModel>(Controller controller, TModel viewModel) { var controllerContext = A.Fake<ControllerContext>(); controller.ControllerContext = controllerContext; var json = new JavaScriptSerializer().Serialize(viewModel); A.CallTo(() => controllerContext.Controller).Returns(controller); A.CallTo(() => controllerContext.HttpContext.Request.InputStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes(json))); A.CallTo(() => controllerContext.HttpContext.Request.ContentType).Returns("application/json"); return controllerContext; }
sumber