如果您使用实体框架,则无法对数据访问层进行单元测试。
Erik Alsmyr 提供的解决方案是非常错误的!看看这里为什么 -内存 IDbSet 有什么意义?.
当您在内存数据库集中使用时,您正在运行 Linq to Objects。当您使用 EF 的 DbContext 时,您的 Linq 将转换为 SQL。这是两种不同的东西!
编写可以在内存数据库集中使用的代码非常容易(您的所有单元测试都会通过,您会很高兴),只是在您第一次尝试访问数据库时注意到运行时错误。
让我们稍微修改一下这段代码。如果我们使用 FIRSTNAME、LASTNAME,我认为 FULLNAME 不应该有 setter。它应该由 FIRSTNAME 和 LASTNAME 计算得出。
class User
{
public string FIRSTNAME { get; set; }
public string LASTNAME { get; set; }
public string FULLNAME
{
get { return string.Format("{0}, {1}", LASTNAME, FIRSTNAME }
}
User(string firstName, string lastName)
{
this.FIRSTNAME = firstName;
this.LASTNAME = lastName;
}
}
现在您可以像这样编写测试并且它会通过(当然在您在控制器中实现它之后)
public IMyEntities GetRepoWithUsers(params User[] users)
{
var inMemoryUsers = new InMemoryDbSet<User>();
var mockData = new Mock<IMyEntities>();
mockData.Setup(m => m.Users).Returns(inMemoryUsers);
return mockData.Object;
}
[Test]
public void GetUserByFullname()
{
var ankaArne = new User("Arne", "Anka");
var bjornBertil = new User("Bertil", "Björn");
var repo = GetRepoWithUsers(ankaArne, bjornBertil);
var usersController = new UsersController(repo);
var found = usersController.GetUser("Anka, Arne");
Assert.NotNull(found);
Assert.AreEqual("Anka", found.LASTNAME);
Assert.AreEqual("Arne", found.FIRSTNAME);
}
但是,当您针对“真实”DbContext 和“真实”DbSet 运行它时,它会抛出,因为您无法对计算的属性进行 Linq 查询。仅在映射到数据库列的那些上。那么这个测试有什么意义呢?