简体   繁体   English

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

[英]Unit test MVC controller with Microsoft Fakes

I have a very basic MVC Controller but I can't figure out how to setup fakes for my Controller action. 我有一个非常基本的MVC控制器,但是我不知道如何为我的控制器动作设置伪造品。 I'm new with this so any help would be great. 我是新来的,所以任何帮助都会很棒。 I use EF 6.1, MVC 5.1 and .NET 4.5.1. 我使用EF 6.1,MVC 5.1和.NET 4.5.1。

Controller: 控制器:

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);
    }
}

Model: 模型:

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; }

}

Test method: 测试方法:

[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");
}

Finally got it to work. 终于让它工作了。 Succeed version: 成功版本:

[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");
        }
    }

You also have to validate the object before submitting the viewModel to your crewate methode. 您还必须先验证对象,然后再将viewModel提交给乘员组方法。 If you don't do that your modelstate is always valid. 如果您不这样做,则您的模型状态始终有效。

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);
        }
    }

A version where in example the email is invalid: First a generic method for validating the method so we can use it for separate properties in the model: 例如,该版本中的电子邮件无效:首先是一种通用方法,用于验证该方法,以便我们可以将其用于模型中的单独属性:

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);
        }
    }

And then the test that calls the method: 然后调用该方法的测试:

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

相关问题 Microsoft.Fakes不会在正常的单元测试上下文中运行 - Microsoft.Fakes won't run in normal unit test contexts 如何使用Microsoft Fakes将Sharepoint对象作为参数对测试方法进行单元化 - How to Unit Test Methods with Sharepoint Objects as parameters with Microsoft Fakes MVC控制器单元测试 - MVC Controller Unit Test 使用Microsoft Fakes进行单元测试-跳过功能 - Unit Testing using Microsoft Fakes - Skipping a function 带伪造的单元测试中的Visual Studio 2015 InvalidProgramException - Visual Studio 2015 InvalidProgramException in Unit Test With Fakes 使用MS假冒品进行单元测试:HttpClient并等待 - Unit Test using MS fakes: HttpClient and await 利用伪造品自动化单元测试DbContext和集成测试 - Automate Unit Testing DbContext and Integration Test With Fakes TFS伪造构建单元测试失败 - TFS Fakes Build Unit test failure 无法使用伪造品调试单元测试用例 - Unable to debug unit test cases using fakes 在 Visual Studio IDE 中运行测试时,单元测试通过,但在使用 vstest.console.exe 和 Microsoft Fakes 时失败 - Unit test passes when running the test from within Visual Studio IDE but fails when using vstest.console.exe and Microsoft Fakes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM