I'm new to Moq, and I'd like to write unit tests using it. I have a database with a few tables, like:
EducationUser | Application
- UsrName - Student
- UsrPwd - CourseId
- UsrChallenge - Date
- IsTeacher - Grade
- FullName
This is a database on a localdb
, which I want to mock. I've created the entities using the Entity Framework. The interface of these entities is IEducationEntities
.
Now I'd like to create a mock object and do some testing of some Web Services, like:
[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");
}
For this, from what I've understood from the documentation , I should be able to do something like:
[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
However, this doesn't work at all, since the entities generated from the databse do not contain information about subfields apparently, and I get the error:
'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?)
What am I missing? How to fill a moq
object with test data that has the same structure as my database?
This article describes how to mock your Entity Framework context (assuming you're using version 6 or later)
You'll do something like this:
[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 ...
}
It'll probably get annoying to configure the mock DbSet
for every entity type for all of your unit tests, so you could make a method to do it.
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;
}
Then your test method becomes
[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 ...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.