EF6 DbSet<T> returns null in Moq - c#

I have a typical Repository Pattern setup in my application with a DbContext (EF6):
public class MyDbContext : EFContext<MyDbContext> {
public MyDbContext () { }
public virtual DbSet<CartItem> Cart { get; set; }
and a repository:
public class GenericEFRepository<TEntity, TContext>
where TEntity : class, new()
where TContext : EFContext<TContext> {
private readonly TContext _context;
public GenericEFRepository(TContext context) {
_context = context;
}
//...
public virtual TEntity Insert(TEntity item) {
return _context.Set<TEntity>().Add(item);
}
I'm testing this with Moq 4.2 (following this tutorial) by creating a mock context:
// Arrange
var mockSet = new Mock<DbSet<CartItem>>();
var mockContext = new Mock<MyDbContext>();
mockContext.Setup(c => c.Cart).Returns(mockSet.Object);
// Act
var service = new GenericEFRepository<CartItem, MyDbContext>(mockContext.Object);
service.Insert(new CartItem() {
Id = 1,
Date = DateTime.Now,
UserId = 1,
Detail = string.Empty
});
// Assert
mockSet.Verify(s => s.Add(It.IsAny<CartItem>()), Times.Once());
The problem is that when I reach this line:
return _context.Set<TEntity>().Add(item);
_context.Set<TEntity>() returns null. After some googling it seems in EF5 it was necessary to return IDbSet<T> for Moq to mock the set, but not with EF6. Is this not the case, or am I missing something?

Add a setup for the Set<T>() method:
mockContext.Setup(c => c.Set<CartItem>()).Returns(mockSet.Object);
Even though on the real EFContext the property Cart and Set<CartItem>() refer to the same object, the mock of the context doesn't know that, so you need to tell it explicitly what to return.
Since it was a loose mock, the call to a method that hasn't been setup returns the default value, which in this case is null. Strict mocks are nice in helping find this error, but also have maintenance costs that other folks don't want to deal with.

This solution is still correct for me at the end of 2020 with EntitiFramework Core.
Not so easy to understand how to mock objects/datasets, I'm starting right now to implement some Integration tests using in-memory DB with mocked data.
I saw my method worked correctly for example if I do:
await _dbcontext.MyEntirySet.ToListAsync();
but failed when using equivalend in a generic Repository
_dbcontext.Set<TEntity> : this return a null dataset.
I can confirm mocking Set fix the problem even with EntityFramework Core.
_dbContextMock.Setup(c => c.Set<MyEntityType>()).Returns(mock.Object);

Related

Unit testing with Moq and a Generic Repository

I'm creating my first test unit with Moq, but cannot seem to make it work.
I have a Generic repository that injects my ApplicationDbContext. I'm trying to recieve a list of all the foods stored in a database. In my real service I use Simple Injector and everything works fine there.
ApplicationDbContext:
public class ApplicationDbContext : IdentityDbContext<AppUser>
{
public ApplicationDbContext()
: base("ApplicationDbContext")
{
}
...
}
Generic repository:
public class Repository<T> : IRepository<T> where T : class
{
private ApplicationDbContext _context;
private readonly IDbSet<T> _entities;
public Repository(ApplicationDbContext context)
{
_context = context;
_entities = _context.Set<T>();
}
.. async methods .. (GetAllAsync)
}
Moq test:
[TestClass]
public class FoodServicesTest
{
private Mock<IRepository<Food>> _foodRepository;
[TestInitialize]
public void Initialize()
{
_foodRepository = new Mock<IRepository<Food>>();
}
[TestMethod]
public async Task CanGetAllFoods()
{
// Before edit 2
//IList<Food> foods = await _foodRepository.Object.GetAllAsync();
//_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foods);
_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(List<Food>());
IList<Food> foods = await _foodRepository.Object.GetAllAsync();
Assert.IsTrue(foods.Count >= 1);
}
}
EDIT 2:
After placing the Setup above GetAllAsync() (thanks to Patrick Quirk) and replacing its parameter to 'new List()' the food list doesn't return a null anymore but a count 0 which presumably is better but I expect it to be 2 (like in service).
the return value is an empty list. this is specified by this line of your code
_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(new List<Food>());
the instruction above is actually telling to the mock object to return a new empty list when GetAllAsync is invoked.
You should instead create new Food objects to "simulate" a result from the database, like so:
var foodList = new List<Food>();
foodList.Add(new Food() { ...insert your mocked values here });
foodList.Add(new Food() { ...insert your mocked values here });
_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foodList);
EDIT
looking better at the code I can only see that you're just using the mock object and see if returns a result. are you sure that is really needed this test? is useful to use mock objects on repositories when there's some business logic involved to be tested. maybe your code was just rewritten for making the question but is worthwhile to point this out.
You can specify the value to return this way:
var foods=new List<Food>();
//// add two items here
foods.Add(new food(){.. set values });
foods.Add(new food(){.. set values });
_foodRepository.Setup(m => m.GetAllAsync()).ReturnsAsync(foods);
IList<Food> foods = await _foodRepository.Object.GetAllAsync();

How to implement FIND method of EF in Unit Test?

I have a Web API 2.0 project that I am unit testing. My controllers have a Unit of Work. The Unit of Work contains numerous Repositories for various DbSets. I have a Unity container in the Web API and I am using Moq in the test project. Within the various repositories, I use the Find method of Entity Framework to locate an entity based on it's key. Additionally, I am using Entity Framework 6.0.
Here is an very general example of the Unit of Work:
public class UnitOfWork
{
private IUnityContainer _container;
public IUnityContainer Container
{
get
{
return _container ?? UnityConfig.GetConfiguredContainer();
}
}
private ApplicationDbContext _context;
public ApplicationDbContext Context
{
get { _context ?? Container.Resolve<ApplicationDbContext>(); }
}
private GenericRepository<ExampleModel> _exampleModelRepository;
public GenericRepository<ExampleModel> ExampleModelRepository
{
get { _exampleModelRepository ??
Container.Resolve<GenericRepository<ExampleModel>>(); }
}
//Numerous other repositories and some additional methods for saving
}
The problem I am running into is that I use the Find method for some of my LINQ queries in the repositories. Based on this article, MSDN: Testing with your own test doubles (EF6 onwards), I have to create a TestDbSet<ExampleModel> to test the Find method. I was thinking about customizing the code to something like this:
namespace TestingDemo
{
class TestDbSet : TestDbSet<TEntity>
{
public override TEntity Find(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefault(b => b.Id == id);
}
}
}
I figured I would have to customize my code so that TEntity is a type of some base class that has an Id property. That's my theory, but I'm not sure this is the best way to handle this.
So I have two questions. Is the approach listed above valid? If not, what would be a better approach for overriding the Find method in the DbSet with the SingleOrDefault method? Also, this approach only really works if their is only one primary key. What if my model has a compound key of different types? I would assume I would have to handle those individually. Okay, that was three questions?
To expand on my comment earlier, I'll start with my proposed solution, and then explain why.
Your problem is this: your repositories have a dependency on DbSet<T>. You are unable to test your repositories effectively because they depend on DbSet<T>.Find(int[]), so you have decided to substitute your own variant of DbSet<T> called TestDbSet<T>. This is unnecessary; DbSet<T> implements IDbSet<T>. Using Moq, we can very cleanly create a stub implementation of this interface that returns a hard coded value.
class MyRepository
{
public MyRepository(IDbSet<MyType> dbSet)
{
this.dbSet = dbSet;
}
MyType FindEntity(int id)
{
return this.dbSet.Find(id);
}
}
By switching the dependency from DbSet<T> to IDbSet<T>, the test now looks like this:
public void MyRepository_FindEntity_ReturnsExpectedEntity()
{
var id = 5;
var expectedEntity = new MyType();
var dbSet = Mock.Of<IDbSet<MyType>>(set => set.Find(It.is<int>(id)) === expectedEntity));
var repository = new MyRepository(dbSet);
var result = repository.FindEntity(id);
Assert.AreSame(expectedEntity, result);
}
There - a clean test that doesn't expose any implementation details or deal with nasty mocking of concrete classes and lets you substitute out your own version of IDbSet<MyType>.
On a side note, if you find yourself testing DbContext - don't. If you have to do that, your DbContext is too far up the stack and it will hurt if you ever try and move away from Entity Framework. Create an interface that exposes the functionality you need from DbContext and use that instead.
Note: I used Moq above. You can use any mocking framework, I just prefer Moq.
If your model has a compound key (or has the capability to have different types of keys), then things get a bit trickier. The way to solve that is to introduce your own interface. This interface should be consumed by your repositories, and the implementation should be an adapter to transform the key from your composite type into something that EF can deal with. You'd probably go with something like this:
interface IGenericDbSet<TKeyType, TObjectType>
{
TObjectType Find(TKeyType keyType);
}
This would then translate under the hood in an implementation to something like:
class GenericDbSet<TKeyType,TObjectType>
{
GenericDbSet(IDbSet<TObjectType> dbset)
{
this.dbset = dbset;
}
TObjectType Find(TKeyType key)
{
// TODO: Convert key into something a regular dbset can understand
return this.dbset(key);
}
}
I realise this is an old question, but after coming up against this issue myself when mocking data for unit tests I wrote this generic version of the 'Find' method that can be used in the TestDBSet implementation that is explained on msdn
Using this method means you dont have to create concrete types for each of your DbSets. One point to note is that this implementaion works if your entities have primary keys in one of the following forms (im sure you could modify to suite other forms easily):
'Id'
'ID'
'id'
classname +'id'
classname +'Id'
classname + 'ID'
public override T Find(params object[] keyValues)
{
ParameterExpression _ParamExp = Expression.Parameter(typeof(T), "a");
Expression _BodyExp = null;
Expression _Prop = null;
Expression _Cons = null;
PropertyInfo[] props = typeof(T).GetProperties();
var typeName = typeof(T).Name.ToLower() + "id";
var key = props.Where(p => (p.Name.ToLower().Equals("id")) || (p.Name.ToLower().Equals(typeName))).Single();
_Prop = Expression.Property(_ParamExp, key.Name);
_Cons = Expression.Constant(keyValues.Single(), key.PropertyType);
_BodyExp = Expression.Equal(_Prop, _Cons);
var _Lamba = Expression.Lambda<Func<T, Boolean>>(_BodyExp, new ParameterExpression[] { _ParamExp });
return this.SingleOrDefault(_Lamba);
}
Also from a performance point of view its not going to be as quick as the recommended method, but for my purposes its fine.
So based on the example, I did the following to be able to Unit Test my UnitOfWork.
Had to make sure my UnitOfWork was implementing IApplicationDbContext. (Also, when I say UnitOfWork, my controller's UnitOfWork is of type IUnitOfWork.)
I left all of the DbSet's in my IApplicationDbContext alone. I chose this pattern once I noticed IDbSet didn't include RemoveRange and FindAsync, which I use throughout my code. Also, with EF6, the DbSet can be set to virtual and this was recommended in MSDN, so that made sense.
I followed the Creating the in-memory test doubles
example to create the TestDbContext and all the recommended classes (e.g. TestDbAsyncQueryProvider, TestDbAsyncEnumerable, TestDbAsyncEnumerator.) Here is the code:
public class TestContext : DbContext, IApplicationDbContext
{
public TestContext()
{
this.ExampleModels= new TestBaseClassDbSet<ExampleModel>();
//New up the rest of the TestBaseClassDbSet that are need for testing
//Created an internal method to load the data
_loadDbSets();
}
public virtual DbSet<ExampleModel> ExampleModels{ get; set; }
//....List of remaining DbSets
//Local property to see if the save method was called
public int SaveChangesCount { get; private set; }
//Override the SaveChanges method for testing
public override int SaveChanges()
{
this.SaveChangesCount++;
return 1;
}
//...Override more of the DbContext methods (e.g. SaveChangesAsync)
private void _loadDbSets()
{
_loadExampleModels();
}
private void _loadExampleModels()
{
//ExpectedGlobals is a static class of the expected models
//that should be returned for some calls (e.g. GetById)
this.ExampleModels.Add(ExpectedGlobal.Expected_ExampleModel);
}
}
As I mentioned in my post, I needed to implement the FindAsync method, so I added a class called TestBaseClassDbSet, which is an alteration of the TestDbSet class in the example. Here is the modification:
//BaseModel is a class that has a key called Id that is of type string
public class TestBaseClassDbSet<TEntity> :
DbSet<TEntity>
, IQueryable, IEnumerable<TEntity>
, IDbAsyncEnumerable<TEntity>
where TEntity : BaseModel
{
//....copied all the code from the TestDbSet class that was provided
//Added the missing functions
public override TEntity Find(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefault(b => b.Id == id);
}
public override Task<TEntity> FindAsync(params object[] keyValues)
{
var id = (string)keyValues.Single();
return this.SingleOrDefaultAsync(b => b.Id == id);
}
}
Created an instance of TestContext and passed that into my Mock.
var context = new TestContext();
var userStore = new Mock<IUserStore>();
//ExpectedGlobal contains a static variable call Expected_User
//to be used as to populate the principle
// when mocking the HttpRequestContext
userStore
.Setup(m => m.FindByIdAsync(ExpectedGlobal.Expected_User.Id))
.Returns(Task.FromResult(ExpectedGlobal.Expected_User));
var mockUserManager = new Mock(userStore.Object);
var mockUnitOfWork =
new Mock(mockUserManager.Object, context)
{ CallBase = false };
I then inject the mockUnitOfWork into the controller, and voila. This implementation seems to be working perfect. That said, based on some feeds I have read online, it will probably be scrutinized by some developers, but I hope some others find this to be useful.

How can I create and populate my mock classes with Autofixture?

Currently I'm using EF6 to implement my repositories inside a UnitOfWork. I also have created an In-Memory mock implementations (MockUnitOfWork & MockRepository) so that I can use them in unit tests, however I now have to deal with the tedious setup of the objects.
Isn't this what Autofixture is designed to do? How would I go about getting a MockUnitOfWork that I can use in my tests that contains Foo and Barr repositories that are populated? I'm using NSubstitute for my mocking framework.
IUnitOfWork
public interface IUnitOfWork
{
void Save();
void Commit();
void Rollback();
IRepository<Foo> FooRepository { get; }
IRepository<Bar> BarRepository { get; }
}
IRepository
public interface IRepository<TEntity> where TEntity : class
{
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null);
TEntity GetByID(object id);
void Insert(TEntity entity);
void Delete(object id);
void Delete(TEntity entityToDelete);
void Update(TEntity entityToUpdate);
}
You're trying to do functional testing here, so it would be wise to have a functional database.
EF can recreate and destroy your database in your setup and teardown methods with a test connection string. This would provide a real functional testing environment for your tests to operate against mimicking the real environment.
Ex:
[TestFixtureSetUp]
public static void SetupFixture() //create database
{
using (var context = new XEntities())
{
context.Setup();
}
}
[TestFixtureTearDown]
public void TearDown() //drop database
{
using (var context = new XEntities())
{
context.Database.Delete();
}
}
[SetUp]
public void Setup() //Clear entities before each test so they are independent
{
using (var context = new XEntities())
{
foreach (var tableRow in context.Table)
{
context.Table.Remove(tableRow);
}
context.SaveChanges();
}
}
Yes, this is exactly what it's designed to do. See the example below. I'm using Mock instead of NSubstitute, because I'm not familiar with NSubstitute. You'll just have to pass another customization, and use NSubstitute syntax in setups.
[SetUp]
public void SetUp()
{
// this will make AutoFixture create mocks automatically for all dependencies
_fixture = new Fixture()
.Customize(new AutoMoqCustomization());
// whenever AutoFixture needs IUnitOfWork it will use the same mock object
// (something like a singleton scope in IOC container)
_fixture.Freeze<Mock<IUnitOfWork>>();
// suppose YourSystemUnderTest takes IUnitOfWork as dependency,
// it'll get the one frozen the line above
_sut = _fixture.Create<YourSystemUnderTest>();
}
[Test]
public void SomeTest()
{
var id = _fixture.Create<object>(); // some random id
var fooObject = _fixture.Create<Foo>(); // the object repository should return for id
// setuping THE SAME mock object that wa passed to _sut in SetUp.
// _fixture.Freeze<Mock part is ESSENTIAL
// _fixture.Freeze<Mock<IUnitOfWork>>() returns the mock object, so whatever comes
// next is Mock specific and you'll have to use NSubstitute syntax instead
_fixture.Freeze<Mock<IUnitOfWork>>()
.Setup(uow => uow.FooRepository.GetById(id))
.Returns(fooObject);
// if this method will ask the unit of work for FooRepository.GetById(id)
// it will get fooObject.
var whatever = _sut.SomeMethod(id);
// do assertions
}
The beautiful thing about AutoFixture is that you don't have to create mocks for all of the dependencies of your system under test. If you're testing a functionality that uses only one dependency, you just Freeze it before creating the system under test. The rest of the dependencies will be mocked automatically.

Proper use of MOQ in a Unit Test

Given the following, is this the proper use of MOQ? I am very new to "mocking", "stubbing", "faking", etc. and just trying to wrap my head around it.
The way I understand it is that this mock is providing a known result, so when I test this service using it, the service reacts properly?
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IQueryable<T> Query();
}
public interface ICustomerService
{
void CreateCustomer(Customer customer);
Customer GetCustomerById(int id);
}
public class Customer
{
public int Id { get; set; }
}
public class CustomerService : ICustomerService
{
private readonly IRepository<Customer> customerRepository;
public CustomerService(IRepository<Customer> customerRepository)
{
this.customerRepository = customerRepository;
}
public Customer GetCustomerById(int id)
{
return customerRepository.Query().Single(x => x.Id == id);
}
public void CreateCustomer(Customer customer)
{
var existingCustomer = customerRepository.Query().SingleOrDefault(x => x.Id == customer.Id);
if (existingCustomer != null)
throw new InvalidOperationException("Customer with that Id already exists.");
customerRepository.Add(customer);
}
}
public class CustomerServiceTests
{
[Fact]
public void Test1()
{
//var repo = new MockCustomerRepository();
var repo = new Mock<IRepository<Customer>>();
repo.Setup(x => x.Query()).Returns(new List<Customer>() { new Customer() { Id = 1 }}.AsQueryable());
var service = new CustomerService(repo.Object);
Action a = () => service.CreateCustomer(new Customer() { Id = 1 });
a.ShouldThrow<InvalidOperationException>();
}
}
I am using xUnit, FluentAssertions and MOQ.
The way I understand it is that this mock is providing a known result,
so when I test this service using it, the service reacts properly?
This statement is correct - the unit test should be verifying that the class you're testing (in this case, CustomerService) is exhibiting the behavior you desire. It's not intended to verify that its dependencies are behaving as expected (in this case, IRepository<Customer>).
Your test is good* - you're setting up your mock for the IRepository and injecting into your SystemUnderTest, and verifying that the CustomerService.CreateCustomer() function is exhibiting the behavior that you expect.
*The overall setup of the test is fine, but I'm not familiar with xUnit, so the final two line's syntax is foreign to me, but it looks like it's correct based on the semantics. For reference, you would do the last two lines in NUnit like so:
Assert.Throws<InvalidOperationException>(() => service.CreateCustomer(...));
The test looks fine to me, the mock just provides a fake repository that returns a hardcoded answer just for the test, so the test only cares about the service you're testing and don't deals with a real-life database or whatever, since you're not testing it here.
I would only add one thing to the test to be even more complete. When you setup method calls on the mocks, make sure they were really called by the system under test. After all, the service is supposed to ask the repo for some object and throw only under a certain return value. Moq in particular provides a syntax for this:
repo.VerifyAll();
What this does is simply checking that the setups you've placed before were actually called at least once. This can protect you from errors where the service just throws the exception right away without calling the repo (easy to spot in examples like yours, but with complex code it's easy to miss a call). With that line, at the end of your test, if your service didn't called the repo asking for the list (and with that specific set of parameters), the test will fail too, even if the exception was properly thrown.

Create service layer with mocked data from LINQ DataContext

I'm using LINQ-to-SQL with ASP.NET MVC 4, and as of this moment I have a repository layer which contacts a real database. This is not very good when I want to unit test.
Also there should never be a logic in the repository layer, so this is why I want to mock the LINQ DataContext so I can create a service layer that talks either to the mock DataContext or to the real DataContext.
I see that my LINQ DataContext class inherits DataContext, but there is no interface, so I can't really mock that. I also see that DataContext uses Table<> class and there exists an interface ITable, so I probably could mock that. Also my LINQ DataContext is a partial class, so maybe I could manipulate that in some kind of way?
When I google this, all articles are from 2008 and are outdated.
Can anyone guide me in the right appropriate direction?
Here is an example of what I want to do. I will have seperate service class for each controller.
public class MyServiceClass
{
IDataContext _context;
// Constructors with dependency injection
public MyServiceClass()
{
_context = new MyRealDataContext();
}
public MyServiceClass(IDataContext ctx)
{
_context = ctx;
}
// Service functions
public IEnumerable<ModelClass> GetAll()
{
return _context.ModelClass;
}
public ModelClass GetOne(int id)
{
return _context.Where(s => s.ID == id).SingleOrDefault();
}
}
Although Linq-to-Sql is still supported in .NET 4+, it has been pushed back in favor of Entity Framework. That's probably why you're finding mostly older articles.
Anyway the best way to go is to write your own DataAccess layer-interface, used through your application. You then can have an implementation of that interface that uses your linq-to-sql for production and a mocked implementation for your unit tests.
Use dependency injection to instantiate the actual implementation class.
For creating a mock implementation you do it either manually (Creating a class in your test project that implements the IDataContext interface but returns hard-coded data) or use one of the mocking frameworks around there.
I have not used every one of them but moq was quite nice. Microsoft has now also their framework in Visual Studio 2012 called Fakes, worth looking at.
Example of using moq
var expectedResultList = new List<ModelClass>(){ ... };
var mockDataContext = new Mock<IDataContext>();
mock.Setup(c => c.GetAll()).Returns(expectedResultList);
MyServiceClass service = new MyServiceClass(mockDataContext.Object);
var list = service.GetAll();
Assert.AreEqual(expectedResultList, list);
In this code you set up your mock object so that it will return your expected list when the GetAll method is called.
This way you can easily test your business logic based on different returns from your data access.
Example of IDataContext
public interface IDataContext<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
int Save(T model);
}
public class LinqToSqlDataContext<T> : IDataContext<T>
{
private DataContext context = new DataContext();
public IEnumerable<T> GetAll()
{
// query datacontext and return enumerable
}
public T GetById(int id)
{
// query datacontext and return object
}
public int Save(T model)
{
// save object in datacontext
}
}
public class MyFirstServiceClass
{
private IDataContext<MyClass> context;
public MyFirstServiceClass(IDataContext<MyClass> ctx)
{
this.context = ctx;
}
....
}
public class MySecondServiceClass
{
private IDataContext<MySecondClass> context;
public MyFirstServiceClass(IDataContext<MySecondClass> ctx)
{
this.context = ctx;
}
....
}

Categories

Resources