C#/Moq - 如何填充多级测试数据?
C#/Moq - How to fill with multi-level test data?
我是 Moq 的新手,我想用它来编写单元测试。我有一个包含几个表的数据库,例如:
EducationUser | Application
- UsrName - Student
- UsrPwd - CourseId
- UsrChallenge - Date
- IsTeacher - Grade
- FullName
这是 localdb
上的一个数据库,我想对其进行模拟。我使用 Entity Framework 创建了实体。这些实体的接口是IEducationEntities
.
现在我想创建一个模拟对象并对某些 Web 服务进行一些测试,例如:
[TestMethod()]
public void LoginTest()
{
HttpResponseMessage response = Request.CreateResponse(_accountController.Login("andrew", "DefaultPassword"));
Assert.IsTrue(response.IsSuccessStatusCode, "User unable to log in with correct login info");
}
为此,根据我从 documentation 中了解到的情况,我应该能够执行以下操作:
[TestClass()]
public class AccountControllerTests : ApiController
{
Mock<IEducationEntities> _entities = new Mock<IEducationEntities>(MockBehavior.Strict);
private AccountController _accountController;
public AccountControllerTests() {
_accountController = new AccountController(_entities.Object);
_entities.Setup(table => table.EducationUsers.UsrName).Returns("andrew");
_entities.Setup(table => table.EducationUsers.UsrPwd).Returns("DefaultPassword");
}
[TestMethod] //etc, defining tests below
然而,这根本不起作用,因为从数据库生成的实体显然不包含有关子字段的信息,我得到错误:
'DbSet' does not contain a definition for 'UsrPwd' and
no extension method 'UsrPwd' accepting a first argument of type
'DbSet' could be found (are you missing a using
directive or an assembly reference?)
我错过了什么?如何使用与我的数据库具有相同结构的测试数据填充 moq
对象?
This article describes how to mock your Entity Framework context(假设您使用的是版本 6 或更高版本)
你会做这样的事情:
[TestMethod]
public void TestSomething()
{
// Create the user data
var educationUsers = new List<EducationUser>
{
new EducationUser
{
UsrName = "andrew",
UsrPwd = "DefaultPassword"
}
}.AsQueryable();
// Create the DbSet that contains the user data and wire it up to return the user data that was created above
Mock<DbSet<EducationUser>> educationUsersDbSet = new Mock<DbSet<EducationUser>>();
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Provider).Returns(educationUsers.Provider);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Expression).Returns(educationUsers.Expression);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.ElementType).Returns(educationUsers.ElementType);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.GetEnumerator()).Returns(educationUsers.GetEnumerator());
// Create the mock context and wire up its EducationUsers property to return the DbSet that was created above
var context = new Mock<IEducationEntities>();
context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object);
// Create the account controller using the mock DbContext
_accountController = new AccountController(context.Object);
// ... the rest of your testing code ...
}
为所有单元测试的每个实体类型配置模拟 DbSet
可能会很烦人,因此您可以创建一个方法来完成它。
public static Mock<DbSet<TEntity>> CreateMockDbSet<TEntity>(IQueryable<TEntity> models) where TEntity : class
{
Mock<DbSet<TEntity>> dbSet = new Mock<DbSet<TEntity>>();
dbSet.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(models.ElementType);
dbSet.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(models.Expression);
dbSet.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(models.GetEnumerator());
dbSet.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(models.Provider);
return dbSet;
}
那么你的测试方法就变成了
[TestMethod]
public void TestSomething()
{
// Create the user data
var educationUsers = new List<EducationUser>
{
new EducationUser
{
UsrName = "andrew",
UsrPwd = "DefaultPassword"
}
}.AsQueryable();
// Create the DbSet that contains the user data and wire it up to return the user data that was created above
Mock<DbSet<EducationUser>> educationUsersDbSet = new CreateMockDbSet(educationUsers);
// Create the mock context and wire up its EducationUsers property to return the DbSet that was created above
var context = new Mock<IEducationEntities>();
context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object);
// Create the account controller using the mock DbContext
_accountController = new AccountController(context.Object);
// ... the rest of your testing code ...
}
我是 Moq 的新手,我想用它来编写单元测试。我有一个包含几个表的数据库,例如:
EducationUser | Application
- UsrName - Student
- UsrPwd - CourseId
- UsrChallenge - Date
- IsTeacher - Grade
- FullName
这是 localdb
上的一个数据库,我想对其进行模拟。我使用 Entity Framework 创建了实体。这些实体的接口是IEducationEntities
.
现在我想创建一个模拟对象并对某些 Web 服务进行一些测试,例如:
[TestMethod()]
public void LoginTest()
{
HttpResponseMessage response = Request.CreateResponse(_accountController.Login("andrew", "DefaultPassword"));
Assert.IsTrue(response.IsSuccessStatusCode, "User unable to log in with correct login info");
}
为此,根据我从 documentation 中了解到的情况,我应该能够执行以下操作:
[TestClass()]
public class AccountControllerTests : ApiController
{
Mock<IEducationEntities> _entities = new Mock<IEducationEntities>(MockBehavior.Strict);
private AccountController _accountController;
public AccountControllerTests() {
_accountController = new AccountController(_entities.Object);
_entities.Setup(table => table.EducationUsers.UsrName).Returns("andrew");
_entities.Setup(table => table.EducationUsers.UsrPwd).Returns("DefaultPassword");
}
[TestMethod] //etc, defining tests below
然而,这根本不起作用,因为从数据库生成的实体显然不包含有关子字段的信息,我得到错误:
'DbSet' does not contain a definition for 'UsrPwd' and no extension method 'UsrPwd' accepting a first argument of type 'DbSet' could be found (are you missing a using directive or an assembly reference?)
我错过了什么?如何使用与我的数据库具有相同结构的测试数据填充 moq
对象?
This article describes how to mock your Entity Framework context(假设您使用的是版本 6 或更高版本)
你会做这样的事情:
[TestMethod]
public void TestSomething()
{
// Create the user data
var educationUsers = new List<EducationUser>
{
new EducationUser
{
UsrName = "andrew",
UsrPwd = "DefaultPassword"
}
}.AsQueryable();
// Create the DbSet that contains the user data and wire it up to return the user data that was created above
Mock<DbSet<EducationUser>> educationUsersDbSet = new Mock<DbSet<EducationUser>>();
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Provider).Returns(educationUsers.Provider);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.Expression).Returns(educationUsers.Expression);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.ElementType).Returns(educationUsers.ElementType);
educationUsersDbSet.As<IQueryable<EducationUser>>().Setup(m => m.GetEnumerator()).Returns(educationUsers.GetEnumerator());
// Create the mock context and wire up its EducationUsers property to return the DbSet that was created above
var context = new Mock<IEducationEntities>();
context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object);
// Create the account controller using the mock DbContext
_accountController = new AccountController(context.Object);
// ... the rest of your testing code ...
}
为所有单元测试的每个实体类型配置模拟 DbSet
可能会很烦人,因此您可以创建一个方法来完成它。
public static Mock<DbSet<TEntity>> CreateMockDbSet<TEntity>(IQueryable<TEntity> models) where TEntity : class
{
Mock<DbSet<TEntity>> dbSet = new Mock<DbSet<TEntity>>();
dbSet.As<IQueryable<TEntity>>().Setup(e => e.ElementType).Returns(models.ElementType);
dbSet.As<IQueryable<TEntity>>().Setup(e => e.Expression).Returns(models.Expression);
dbSet.As<IQueryable<TEntity>>().Setup(e => e.GetEnumerator()).Returns(models.GetEnumerator());
dbSet.As<IQueryable<TEntity>>().Setup(e => e.Provider).Returns(models.Provider);
return dbSet;
}
那么你的测试方法就变成了
[TestMethod]
public void TestSomething()
{
// Create the user data
var educationUsers = new List<EducationUser>
{
new EducationUser
{
UsrName = "andrew",
UsrPwd = "DefaultPassword"
}
}.AsQueryable();
// Create the DbSet that contains the user data and wire it up to return the user data that was created above
Mock<DbSet<EducationUser>> educationUsersDbSet = new CreateMockDbSet(educationUsers);
// Create the mock context and wire up its EducationUsers property to return the DbSet that was created above
var context = new Mock<IEducationEntities>();
context.Setup(e => e.EducationUsers).Returns(educationUsersDbSet.Object);
// Create the account controller using the mock DbContext
_accountController = new AccountController(context.Object);
// ... the rest of your testing code ...
}