繁体   English   中英

使用Microsoft Fakes进行单元测试MVC控制器

[英]Unit test MVC controller with Microsoft Fakes

我有一个非常基本的MVC控制器,但是我不知道如何为我的控制器动作设置伪造品。 我是新来的,所以任何帮助都会很棒。 我使用EF 6.1,MVC 5.1和.NET 4.5.1。

控制器:

public class MemberController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Id,FirstName,LastName,BirthDay,MemberSince,Street,HouseNumber,Addition,ZipCode,City")] MemberCreateViewModel memberCreate)
    {
        if (ModelState.IsValid)
        {
            Mapper.CreateMap<MemberCreateViewModel, Member>();
            var member = Mapper.Map<Member>(memberCreate);

            db.Members.Add(member);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(memberCreate);
    }
}

模型:

public class MemberCreateViewModel
{

    [Display(Name = "Voornaam")]
    [Required]
    [StringLength(50)]
    public string FirstName { get; set; }

    [Display(Name = "Achternaam")]
    [Required]
    [StringLength(50)]
    public string LastName { get; set; }

    [Display(Name = "Geboortedatum")]
    [Required]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime BirthDay { get; set; }

    [Display(Name = "Lid sinds")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime MemberSince { get; set; }

    [Display(Name = "Straat")]
    [Required]
    [StringLength(100)]
    public string Street { get; set; }

    [Display(Name = "Huisnummer", ShortName = "Huisnr")]
    [Required]
    [Range(1, 5000)]
    public int HouseNumber { get; set; }

    [Display(Name = "Toevoeging")]
    public string Addition { get; set; }

    [Display(Name = "Postcode")]
    [Required]
    [StringLength(6, MinimumLength = 6)]
    public string ZipCode { get; set; }

    [Display(Name = "Plaats")]
    [Required]
    [StringLength(40)]
    public string City { get; set; }

    [Display(Name = "Telefoonnummer", ShortName = "Telnr")]
    [StringLength(10, MinimumLength = 10)]
    public string PhoneNumber { get; set; }

    [Display(Name = "Mobiel")]
    [StringLength(10, MinimumLength = 10)]
    public string MobileNumber { get; set; }

    [Display(Name = "E-mail")]
    [Required]
    [EmailAddress]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

}

测试方法:

[TestMethod]
public void CreateSave()
{
    var mockSet = new StubDbSet<Member>();
    var mockContext = new StubApplicationDbContext()
    {   
    //Members = () =>
    //  {
    //      return new StubDbSet<Member>();
    //  }
    };

    // Arrange
    MemberController controller = new MemberController();

    MemberCreateViewModel vm = new MemberCreateViewModel()
    {
            Addition = "A",
            BirthDay = new DateTime(1995, 10, 14),
            City = "Rotterdam",
            Email = "test.user@fake.com",
            FirstName = "Test",
            HouseNumber = 4,
            LastName = "Persoon",
            MemberSince = new DateTime(2007, 10, 8),
            MobileNumber = "1234567890",
            PhoneNumber = "1234567890",
            Street = "Staartmanslaan",
            ZipCode = "3134kl"
    };

    // Act
    ViewResult result = controller.Create(vm) as ViewResult;

    // Assert
    Assert.IsNotNull(result);
    Assert.AreEqual(result.ViewName, "Index");
}

终于让它工作了。 成功版本:

[TestMethod]
    public void CreateMemberSucceededTest()
    {
        using (ShimsContext.Create())
        {               
            // Arrange
            var mockSet = new StubDbSet<Member>();

            ShimApplicationDbContext.Constructor = (t) => { };
            ShimApplicationDbContext.AllInstances.MembersGet = (t) =>
            {
                return mockSet;
            };
            ShimDbContext.AllInstances.SaveChanges = (t) => { return 1; };

            MemberController controller = new MemberController();

            MemberCreateViewModel vm = new MemberCreateViewModel()
            {
                Addition = "A",
                BirthDay = new DateTime(1995, 10, 14),
                City = "Rotterdam",
                Email = "test.user@fake.com",
                FirstName = "Test",
                HouseNumber = 4,
                LastName = "Persoon",
                MemberSince = new DateTime(2007, 10, 8),
                MobileNumber = "1234567890",
                PhoneNumber = "1234567890",
                Street = "Staartmanslaan",
                ZipCode = "3134kl"
            };

            // Act
            Validate(controller, vm);
            var result = controller.Create(vm) as RedirectToRouteResult;

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(result.RouteValues["action"], "Index");
        }
    }

您还必须先验证对象,然后再将viewModel提交给乘员组方法。 如果您不这样做,则您的模型状态始终有效。

private static void Validate(MemberController controller, object entityToValidate)
    {
        var valResults = TryValidate(entityToValidate);
        SetErrorInModelState(valResults, controller);
    }

    internal static Collection<ValidationResult> TryValidate(object entityToValidate)
    {
        var result = new Collection<ValidationResult>();

        Validator.TryValidateObject(entityToValidate, new ValidationContext(entityToValidate, null, null), result, true);

        return result;
    }

    internal static void SetErrorInModelState(Collection<ValidationResult> validationErrors, Controller controller)
    {
        foreach (var validationError in validationErrors)
        {
            controller.ModelState.AddModelError(validationError.MemberNames.First(), validationError.ErrorMessage);
        }
    }

例如,该版本中的电子邮件无效:首先是一种通用方法,用于验证该方法,以便我们可以将其用于模型中的单独属性:

private static void CreateMemberValidationTest(MemberCreateViewModel vm, string propertyThatFails)
    {
        using (ShimsContext.Create())
        {
            // Arrange
            var mockSet = new StubDbSet<Member>();

            ShimApplicationDbContext.Constructor = (t) => { };
            ShimApplicationDbContext.AllInstances.MembersGet = (t) =>
            {
                return mockSet;
            };
            ShimDbContext.AllInstances.SaveChanges = (t) => { return 1; };

            MemberController controller = new MemberController();

            // Act
            Validate(controller, vm);
            var result = controller.Create(vm) as ViewResult;

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(result.ViewData.ModelState.Count, 1);
            Assert.AreEqual(result.ViewData.ModelState.Keys.First(), propertyThatFails);
        }
    }

然后调用该方法的测试:

[TestMethod]
    public void CreateMemberNoEmailTest()
    {
        var vm = new MemberCreateViewModel()
        {
            Addition = "A",
            BirthDay = new DateTime(1995, 10, 14),
            City = "Rotterdam",
            Email = null,
            FirstName = "Test",
            HouseNumber = 4,
            LastName = "Persoon",
            MemberSince = new DateTime(2007, 10, 8),
            MobileNumber = "1234567890",
            PhoneNumber = "1234567890",
            Street = "Staartmanslaan",
            ZipCode = "3134kl"
        };

        CreateMemberValidationTest(vm, "Email");
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM