如何测试项目是否已添加到模拟的DbContext?

时间:2014-09-23 13:57:08

标签: entity-framework nunit moq

我的问题类似于this one

然而,在我的情况下,没有一个答案是可以接受的。我已经实现了Microsoft建议here的几个类,并且一直在努力应对我觉得很常见的场景。

我需要测试在控制器操作中创建的项目是否正确保存到数据库中。这是控制器方法:

[HttpPost]
[ActionName("CreateUser")]
public virtual async Task<IHttpActionResult> CreateUser(RegisterViewModel viewModel)
{
    ApplicationUser user = new ApplicationUser(false, true, true, viewModel.UserName,
        viewModel.FirstName, viewModel.LastName, viewModel.EmailAddress);

    try
    {
        user.Salt = HashUtilities.GetSalt();
        user.Password = HashUtilities.GetHashedValue(viewModel.Password, user.Salt);

        // This is what I want to assert happened
        _dbContext.ApplicationUsers.Add(user);

        await _dbContext.SaveChangesAsync();
        return Ok(user);                
    }
    catch (DbEntityValidationException ex)
    {
        List<string> messages = new List<string>();
        foreach (DbEntityValidationResult eve in ex.EntityValidationErrors)
            foreach (DbValidationError dve in eve.ValidationErrors)
                messages.Add(dve.ErrorMessage);

        string message = string.Join("\n\n", messages);

        return BadRequest(message);
    }
    catch (Exception ex)
    {
        return InternalServerError(ex);
    }
}

这是我的考验。某些类/方法实现(例如InMemoryAsyncQueryable)直接从MS在codeplex链接上的建议中复制。

// Arrange            
var viewModel = new RegisterViewModel
{
    ConfirmPassword = "abc123",
    EmailAddress = "Test@test.com",
    FirstName = "Test",
    LastName = "User1",
    Password = "abc123",
    UserName = "TestUser1" 
};
var queryableUsers = new List<ApplicationUser>().AsQueryable();
var users = DataUtilities.CreateMockQueryableSet<ApplicationUser>(new InMemoryAsyncQueryable<ApplicationUser>(queryableUsers));                     

var mockContext = new Mock<MainContext>();
mockContext.Setup(x => x.ApplicationUsers).Returns(users.Object);

var controller = new ApplicationUserController(mockContext.Object);

// Act
var result = controller.CreateUser(viewModel).Result;

// Assert            
Assert.IsInstanceOf<OkNegotiatedContentResult<ApplicationUser>>(result);           
mockContext.Verify(x => x.SaveChangesAsync());

// Test for persistence to the DbSet this is what is breaking down.  
// My ApplicationUsers.Count() is 0 when I'm expecting 1.
Assert.AreEqual(mockContext.Object.ApplicationUsers.Count(), 1);
var testUser = mockContext.Object.ApplicationUsers.First();

1 个答案:

答案 0 :(得分:0)

坦率地说,我发现测试这种行为真的很困难。我建议你看看内存中DbContext包装的解决方案,例如the Effort library

我在this answer中解释了我如何使用它:它适用于实体框架,但我认为在您的情况下可以使用相同的行为。