C# 模拟非虚拟发布模型属性和方法
我将person模型类定义为:C# 模拟非虚拟发布模型属性和方法,c#,asp.net-mvc,unit-testing,moq,C#,Asp.net Mvc,Unit Testing,Moq,我将person模型类定义为: public class PersonModel { public bool SelectionSubmitted = false; public bool ShowValidationSummary = false; public string Name; public string Get() { //actual implementation return some val
public class PersonModel
{
public bool SelectionSubmitted = false;
public bool ShowValidationSummary = false;
public string Name;
public string Get()
{
//actual implementation return some value from the db
return string.Empty;
}
}
控制器的实现如下所示:
class HomeController : Controller
{
[HttpGet]
public ActionResult Index(PersonModel model)
{
if (model.SelectionSubmitted && !ValidateSelections(model))
{
model.ShowValidationSummary = true;
}
return View("Index", model.Get());
}
private bool ValidateSelections(PersonModel model)
{
if(model.Name == "")
{
ModelState.AddModelError("EmptyPersonName", "Person name cannot be null");
}
return ModelState.IsValid;
}
}
测试类别和方法定义为:
[TestClass]
public class ChildWithoutPlacementControllerTest
{
private readonly Mock<PersonModel> _mockPersonModel;
public ChildWithoutPlacementControllerTest()
{
_mockPersonModel = new Mock<PersonModel>();
}
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown()
{
//Arrange
HomeController controller = new HomeController();
_mockPersonModel.Setup(x => x.Get()).Returns(It.IsAny<string>());
_mockPersonModel.SetupGet(x => x.Name).Returns(string.Empty);
_mockPersonModel.SetupGet(x => x.SelectionSubmitted).Returns(true);
//Act
controller.Index(_mockPersonModel.Object);
//Assert
var isShowSummarySetToTrue = _mockPersonModel.Object.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
}
[TestClass]
公共班级无职儿童控制员测试
{
私有只读Mock\u mockPersonModel;
无职业介绍的公共儿童控制员测试()
{
_mockPersonModel=新建Mock();
}
[测试方法]
当申请未来出生日期时,应显示验证消息()
{
//安排
HomeController=新的HomeController();
_mockPersonModel.Setup(x=>x.Get()).Returns(It.IsAny());
_SetupGet(x=>x.Name).Returns(string.Empty);
_mockPersonModel.SetupGet(x=>x.SelectionSubmitted)。返回(true);
//表演
controller.Index(_mockPersonModel.Object);
//断言
变量isShowSummarySetToTrue=\u mockPersonModel.Object.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
}
我想要实现的是将SelectionSubmitted
和Name
属性分别模拟为true
和string.Empty
以及Setup
类的Get
方法,并检查测试返回对象是否已将ShowValidationSummary
设置为true
但是,我发现我无法设置非虚拟财产名称
我是否做错了什么,或者是否有任何方法可以在不更改实现代码的情况下做到这一点
我做错什么了吗
这似乎是一个错误
有没有办法在不改变实现代码的情况下实现它
在这种情况下,确实不需要最低起订量。您可以使用继承来创建一个假模型,以便在测试中使用。伪模型将覆盖与数据库紧密耦合的方法。(稍后将详细介绍)
然后可以重构测试以使用假模型,并按照预期完成测试
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown() {
//Arrange
var fakePersonModel = new FakePerson() {
Name = string.Empty,
SelectionSubmitted = true
};
var controller = new HomeController();
//Act
controller.Index(fakePersonModel);
//Assert
var isShowSummarySetToTrue = fakePersonModel.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
除此之外,如果实际的Get
实现如您所述,那么您的模型似乎做了很多工作
实际实现从数据库返回一些值
考虑将该功能重构为服务(单一责任原则/关注点分离)
并尽可能保持模型的精益。还考虑将这些公共字段重构为公共属性。
public class PersonModel {
public bool SelectionSubmitted { get; set; }
public bool ShowValidationSummary { get; set; }
public string Name { get; set; }
}
控制器将依赖于服务抽象
class HomeController : Controller {
private IPersonModelService service;
public HomeController(IPersonModelService service) {
this.service = service;
}
[HttpGet]
public ActionResult Index(PersonModel model) {
if (model.SelectionSubmitted && !ValidateSelections(model)) {
model.ShowValidationSummary = true;
}
return View("Index", service.Get(model));
}
private bool ValidateSelections(PersonModel model) {
if (model.Name == "") {
ModelState.AddModelError("EmptyPersonName", "Person name cannot be null");
}
return ModelState.IsValid;
}
}
现在,测试可以单独进行到完成
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown() {
//Arrange
var model = new PersonModel() {
Name = string.Empty,
SelectionSubmitted = true
};
var serviceMock = new Mock<IPersonModelService>();
serviceMock.Setup(_ => _.Get(It.IsAny<PersonModel>())).Returns(string.Empty);
var controller = new HomeController(serviceMock.Object);
//Act
controller.Index(model);
//Assert
var isShowSummarySetToTrue = model.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
[TestMethod]
当申请未来出生日期时,应显示验证消息(){
//安排
var model=newpersonmodel(){
Name=string.Empty,
SelectionSubmitted=true
};
var serviceMock=new Mock();
serviceMock.Setup(=>wk.Get(It.IsAny())).Returns(string.Empty);
var控制器=新的HomeController(serviceMock.Object);
//表演
控制器索引(模型);
//断言
var isShowSummarySetToTrue=model.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
可能与@nkosi重复我猜你发布了答案,但现在找不到。这确实帮助了我,这种方法对我很有效。非常感谢!!。我发现了它的一个问题,并且正在检查这个问题。你应该考虑重构你的代码以使它更易于测试。是的,我正在研究如何使它更易于测试。
class HomeController : Controller {
private IPersonModelService service;
public HomeController(IPersonModelService service) {
this.service = service;
}
[HttpGet]
public ActionResult Index(PersonModel model) {
if (model.SelectionSubmitted && !ValidateSelections(model)) {
model.ShowValidationSummary = true;
}
return View("Index", service.Get(model));
}
private bool ValidateSelections(PersonModel model) {
if (model.Name == "") {
ModelState.AddModelError("EmptyPersonName", "Person name cannot be null");
}
return ModelState.IsValid;
}
}
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown() {
//Arrange
var model = new PersonModel() {
Name = string.Empty,
SelectionSubmitted = true
};
var serviceMock = new Mock<IPersonModelService>();
serviceMock.Setup(_ => _.Get(It.IsAny<PersonModel>())).Returns(string.Empty);
var controller = new HomeController(serviceMock.Object);
//Act
controller.Index(model);
//Assert
var isShowSummarySetToTrue = model.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}