Mock Generic Repository with contexts - c#

I have a generic repository for several contexts. I can extend it and use it for services without problem. However, When I mock it, this.Entities in the constructor is always null.
GenericDataRepsository
public class GenericDataRepository<T, C> : IGenericDataRepository<T, C> where T : class where C : DbContext, new() {
protected C context;
protected IDbSet<T> Entities;
public GenericDataRepository() {
this.context = new C();
this.Entities = context.Set<T>();
}
public GenericDataRepository(C context) {
this.context = context;
this.Entities = context.Set<T>(); // Problem is here. Entities didn't get set when mocking
}
public virtual IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate) {
return Entities.Where(predicate).ToList();
}
// omitted Add, Update, Delte
}
Unit Test
[Test]
public void GetBIlloTo() {
var data = new List<BillTo> {
new BillTo { CONTACTID = 12, COUNTRY = "USA" }
}.AsQueryable();
var mockSet = Substitute.For<DbSet<BillTo>, IQueryable<BillTo>>();
((IQueryable<BillTo>)mockSet).Provider.Returns(data.Provider);
((IQueryable<BillTo>)mockSet).Expression.Returns(data.Expression);
((IQueryable<BillTo>)mockSet).ElementType.Returns(data.ElementType);
((IQueryable<BillTo>)mockSet).GetEnumerator().Returns(data.GetEnumerator());
var mockContext = Substitute.For<MyEntities>();
mockContext.BillToes.Returns(mockSet);
var repo = new GenericDataRepository<BillTo, MyEntities>(mockContext);
//// Act
var actual = repo.FindBy(r => r.CONTACTID == 12);
//// Assert
Assert.AreEqual(actual.Count(), 1);
}
MyEntities - generated by EF and I didn't change it.
public partial class MyEntities : DbContext
{
public MyEntities()
: base("name=MyEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<BillTo> BillToes { get; set; }
}
I'm using EF database first, NUnit, and Nsubstitute. Tried Moq as well, same problem. So, Why didn't Entities get set?

You didn't set your mock object to return any value using the method set<T>.
Just add the following call before you initialize your class under test:
mockContext.Set<BillTo>().Returns(mockSet);

Why have a FindBy method at all? Why not have a FindAll() that returns the the this.Entities = context.Set() something like
public IQueryable<T> FindAll()
{
return _context.Set<T>());
}
Then the user of the repository can tack on any linq predicate they want
and you can mock or fake the FindAll() method to return whatever list of entities you want.

Related

NSubstitute and DbContext.Set<TEntity> Could not find a call to return from

I am trying to write some tests for an existing service we have. It uses the DbContext (In our case, named DatabaseContext) and the constructor looks like this:
public GenericOrderProvider(DatabaseContext context, IOrderHandler<T> orderHandler)
{
_orderHandler = orderHandler;
_context = context;
_dbSet = context.Set<T>();
}
As you can see, it's generic and sets the _dbSet when it's initialized.
I have this very simple method:
public Attempt<IQueryable<T>> List(params string[] includes)
{
var x = _dbSet.ToList();
return Attempt<IQueryable<T>>.Succeed(_dbSet.OrderBy(m => m.Order));
}
And I wrote this test:
[TestFixture]
public class ListShould
{
[Test]
public void ReturnList()
{
// Assemble
var services = GenericOrderProviderContext.GivenServices();
var provider = services.WhenCreateOrderProvider();
services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet());
//services.DatabaseContext.Attributes = new List<Attribute>().ToDbSet();
// Act
var result = provider.List();
// Assert
result.Failure.Should().BeFalse();
result.Result.Count().Should().Be(0);
}
}
When I run that test, I get the error:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.
The trace specifically targets the line services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(new List<Attribute>().ToDbSet()); but I have no idea how to fix it.
As far as I can tell, I am mapping to the right method.
For completeness, here is my test Contexts:
public class GenericOrderProviderContext: DatabaseContextContext<GenericOrderProviderContext>
{
public static GenericOrderProviderContext GivenServices() => new GenericOrderProviderContext();
public IGenericOrderProvider<Attribute> WhenCreateOrderProvider() =>
new GenericOrderProvider<Attribute>(DatabaseContext,
new OrderHandler<Attribute>(DatabaseContext));
public bool IsSequential(List<Attribute> models)
{
return !models.OrderBy(m => m.Order).Select(m => m.Order).Select((i, j) => i - j).Distinct().Skip(1).Any();
}
}
public class DatabaseContextContext<T> where T: DatabaseContextContext<T>
{
public DatabaseContext DatabaseContext;
protected DatabaseContextContext()
{
DatabaseContext = Substitute.For<DatabaseContext>();
}
}
Does anyone know what I can do to resolve this issue?

Testing a ViewModel in WPF MVVM with Moq framework

I am new to Moq framework. I have a viewmodel with injected IEntityRepository
public class MainViewModel
{
private readonly IEntityRepository _entityRepository;
public MainViewModel(IEntityRepository entityRepository)
{
_entityRepository = entityRepository;
Entities = new ObservableCollection<EntityWrapper>();
}
public ObservableCollection<EntityWrapper> Entities { get; set; }
public void Load()
{
var entities = _entityRepository.GetAll();
Entities.Clear();
foreach (var entity in entities)
{
Entities.Add(new EntityWrapper(entity));
}
}
public void AddEntity(string name, int x, int y)
{
var entity = new Entity()
{
Name = name,
X = x,
Y = y
};
_entityRepository.AddEntity(entity);
_entityRepository.Save();
}
}
and EntityRepository is like this:
public class EntityRepository : IEntityRepository
{
private Context _context;
public EntityRepository(Context context)
{
_context = context;
}
public Entity Get(long id)
{
return _context.Entities.Find(id);
}
public IEnumerable<Entity> GetAll()
{
return _context.Entities.ToList();
}
public void AddEntity(Entity entity)
{
_context.Entities.Add(entity);
}
public void Save()
{
_context.SaveChanges();
}
}
Now, I want to test Load and AddEntity methods of MainViewModel
this is my test class:
[TestClass]
public class MainViewModelTests
{
private Mock<IEntityRepository> _mockRepo;
private MainViewModel _mainViewModel;
public MainViewModelTests()
{
_mockRepo = new Mock<IEntityRepository>();
_mainViewModel = new MainViewModel(_mockRepo.Object);
}
[TestMethod]
public void AddEntityTest()
{
var entity = new Entity()
{
Name = "Student",
X = 10,
Y = 20
};
_mainViewModel.AddEntity("Student", 10, 20);
_mockRepo.Setup(m => m.AddEntity(entity));
_mockRepo.Setup(m => m.Save());
var entities = _mainViewModel.Entities;
Assert.AreEqual(1, entities.Count);
}
[TestMethod]
public void LoadTest()
{
// How to add fake data???
_mockRepo.Setup(r => r.GetAll());
_mainViewModel.Load();
var entities = _mainViewModel.Entities;
Assert.AreEqual(1, entities.Count);
}
}
In AddEntityTest() I don't know why the property Entities will be empty and in LoadTest how to populate fake data so that I can load it.
To get a test data in LoadTest method you can use Moq Returns method
_mockRepo.Setup(r => r.GetAll()).Returns(new List<Entity> { new Entity() });
It works, because List<T> implements IEnumerable<T>.
As for the AddEntityTest, there are a couple of issues here. You setup the mock
_mockRepo.Setup(m => m.AddEntity(entity));
_mockRepo.Setup(m => m.Save());
after _mainViewModel.AddEntity("Student", 10, 20); call. It should come before, Arrange step is always before Act step, according to AAA pattern
You also don't update Entities collection after adding an entity, so the Entities.Count remains the same. I suggest you to setup a IEntityRepository.GetAll() mock as well for this test and update an Entities collection in MainViewModel. Or rewrite the logic of your AddEntityTest, if collection update performed through view

How to mock IRepository<T>?

I want to mock a unit of work interface with repositories inside for unit test purpose. So far I am able to do it like below.
namespace Liquid.Service.UnitTest
{
using Liquid.DataAccess.Interface;
using Liquid.Domain;
using Domain.Interface;
using Moq;
using System.Collections.Generic;
using System.Linq;
internal class Helper
{
internal Mock<IUnitOfWork> MockUnitOfWork(ICollection<Dummy> dummies = null,
ICollection<ProductType> productTypes = null)
{
dummies = dummies ?? new List<Dummy>();
productTypes = productTypes ?? new List<ProductType>();
var dummyRepositoryMock = MockDummyRepository(dummies);
var productTypeRepositoryMock = MockProductTypeRepository(productTypes);
var unitOfWorkMock = new Mock<IUnitOfWork>();
unitOfWorkMock.Setup(x => x.DummyRepository)
.Returns(dummyRepositoryMock.Object);
unitOfWorkMock.Setup(x => x.ProductTypeRepository)
.Returns(productTypeRepositoryMock.Object);
return unitOfWorkMock;
}
private Mock<IDummyRepository> MockDummyRepository(ICollection<Dummy> dummies)
{
var dummyRepositoryMock = new Mock<IDummyRepository>();
dummyRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
.Returns((int arg1) => dummies.Where(x => x.Id == arg1).SingleOrDefault());
dummyRepositoryMock.Setup(x => x.Add(It.IsAny<Dummy>()))
.Callback((Dummy arg1) => dummies.Add(arg1));
return dummyRepositoryMock;
}
private Mock<IProductTypeRepository> MockProductTypeRepository(ICollection<ProductType> productTypes)
{
var productTypeRepositoryMock = new Mock<IProductTypeRepository>();
productTypeRepositoryMock.Setup(x => x.FindById(It.IsAny<int>()))
.Returns((int arg1) => productTypes.SingleOrDefault(x => x.Id == arg1));
productTypeRepositoryMock.Setup(x => x.Add(It.IsAny<ProductType>()))
.Callback((ProductType arg1) => productTypes.Add(arg1));
return productTypeRepositoryMock;
}
}
}
You see that I've created two method to mock DummyRepository and ProductTypeRepository but because it has same implementation, I think it is redundant for every repositories I have.
Below is the Repositories and IRepository code.
namespace Liquid.DataAccess.Interface
{
using Liquid.Domain;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public interface IDummyRepository : IRepository<Dummy>
{
}
public interface IProductTypeRepository : IRepository<ProductType>
{
}
public interface IRepository<TEntity> where TEntity : class
{
IList<TEntity> GetAll();
Task<List<TEntity>> GetAllAsync();
Task<List<TEntity>> GetAllAsync(CancellationToken cancellationToken);
IList<TEntity> PageAll(int skip, int take);
Task<List<TEntity>> PageAllAsync(int skip, int take);
Task<List<TEntity>> PageAllAsync(CancellationToken cancellationToken, int skip, int take);
TEntity FindById(object id);
Task<TEntity> FindByIdAsync(object id);
Task<TEntity> FindByIdAsync(CancellationToken cancellationToken, object id);
void Add(TEntity entity);
void Update(TEntity entity);
void Remove(TEntity entity);
}
}
How can I use a same method to mock every repositories implementation which inherits IRepository?
UPDATE :
The test is just a simple add and check like below.
[Test]
public void ProductTypeService_Add()
{
// GIVEN
var productTypeData = new ProductType()
{
Id = 1,
Description = "ProductType1"
};
// WHEN
var unitOfWorkMock = new Helper().MockUnitOfWork();
var productTypeService = new ProductTypeService(unitOfWorkMock.Object);
productTypeService.Add(productTypeData);
unitOfWorkMock.Verify(x => x.SaveChanges());
// THEN
Assert.That(productTypeService.FindById(1) != null);
Assert.That(productTypeService.FindById(2) == null);
// WHEN
var productTypeData2 = new ProductType()
{
Id = 2,
Description = "ProductType2"
};
productTypeService.Add(productTypeData2);
// THEN
Assert.That(productTypeService.FindById(2) != null);
}
IMHO you are testing the wrong thing; namely you are testing that an in-memory collection (a List<T>) can store data and the data can be found in the collection. This always yields true because that is the purpose of in-memory collections.
Instead of doing this you either need to create integration tests which will use the actual implementation of the underlying repository (such as Entity Framework) or just test the behavior of your service like this:
[Test]
public void ProductTypeService_WhenAddingNewItem_CallsSaveChanges()
{
var unitOfWork = new Mock<IUnitOfWork>();
// setup the properties of the mock here...
var service = new ProductTypeService(unitOfWork);
service.Add(new ProductType { Id = 2, Description = "some product" });
unitOfWork.AssertWasCalled(_ => _.SaveChanges());
}
This way, you test that your service calls SaveChanges() method; actually saving the data is the responsibility of the repository and as I said above, testing that a list can store data in memory is useless.
I think you have over complicated your question and thus your solution. You don't need interfaces for your various repositories like IDummyRepository and IProductRepository if you are not adding any value to it.
Your data classes
public class Dummy
{
public int Id { get; set; }
}
public class ProductType
{
public int Id { get; set; }
}
Your ProductTypeService (I can only assume this)
public class ProductTypeService
{
private readonly IUnitOfWork _unitOfWork;
public ProductTypeService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddProductType(ProductType productType)
{
_unitOfWork.ProductTypes.Add(productType);
}
}
Your IUnitOfWork
public interface IUnitOfWork
{
IRepository<Dummy> Dummies { get; set; }
IRepository<ProductType> ProductTypes { get; set; }
}
Your IRepository remains unchanged so I won't copy paste it here!
Finally your unit test
[TestFixture]
public class Class1
{
private Mock<IUnitOfWork> _unitOfWorkMock;
private Mock<IRepository<Dummy>> _dummyRepositoryMock;
private Mock<IRepository<ProductType>> _productTypeRepositoryMock;
[SetUp]
public void Setup()
{
_unitOfWorkMock = new Mock<IUnitOfWork>();
_dummyRepositoryMock = CreateMock<Dummy>();
_productTypeRepositoryMock = CreateMock<ProductType>();
_unitOfWorkMock.Setup(u => u.Dummies).Returns(_dummyRepositoryMock.Object);
_unitOfWorkMock.Setup(u => u.ProductTypes).Returns(_productTypeRepositoryMock.Object);
}
[Test]
public void product_type_service_should_add_item_to_the_underlying_repository()
{
var productTypeService = new ProductTypeService(_unitOfWorkMock.Object);
var productType = new ProductType {Id = 10};
productTypeService.AddProductType(productType);
_productTypeRepositoryMock.Verify(r => r.Add(It.Is<ProductType>(p => p.Id == productType.Id)), Times.Once());
}
private Mock<IRepository<T>> CreateMock<T>() where T : class
{
var mock = new Mock<IRepository<T>>();
// do more common magic here
return mock;
}
}

C# database abstraction class with Entity Framework

I want to create a common database abstraction in order to expose the same interface without worrying about the type of the DbContext that the database manage.
Here there is an example in order to explain well the concept:
public interface IDatabase<T> where T : DbContext {
void Add<T>(T entity);
void Remove<T>(T entity);
void SaveChanges();
}
The implementation can be:
public MyDatabase<T> : IDatabase<T> where T : MyContext {
public T Context { get; private set; }
//singleton contructor ...
public void Add<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void Remove<TC>(TC entity) {
Context.Set<TC>().Add(entity);
}
public void SaveChanges {
Context.SaveChanges();
}
}
The goals of this design are different: expose the same interface in order to decouple logic from database, change quickly the database (context), create one time the context and reuse during all the application lifetime (lock mechanism are required).
The problem is that the interface hides all the types of the sets in the context.
Context.Set<TC>().Add(entity); //this line don't compile
I'm not sure that this design is the best practise. How can I implement a design that offers these features?
Why you does not use the standard pattern for example Repository pattern you can also combine it with UnitOfWork.
You make it complicated for your self, just check this.
public interface IMyClassRepository : IDisposable
{
IQueryable<MyClass> All { get; }
IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties);
MyClass Find(int id);
void InsertOrUpdate(MyClass myClass);
void Delete(int id);
void Save();
}
public class MyClassRepository : IMyClassRepository
{
DBContext context = new DBContext();
public IQueryable<MyClass> All
{
get { return context.Employees; }
}
public IQueryable<MyClass> AllIncluding(params Expression<Func<MyClass, object>>[] includeProperties)
{
IQueryable<MyClass> query = context.MyClasses;
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
return query;
}
public MyClass Find(int id)
{
return context.MyClasses.Find(id);
}
public void InsertOrUpdate(MyClass myClass)
{
if (myClass.Id == default(int))
{
// New entity
context.MyClasses.Add(myClass);
}
else
{
// Existing entity
context.Entry(myClass).State = EntityState.Modified;
}
}
public void Delete(int id)
{
var employee = context.Employees.Find(id);
context.Employees.Remove(employee);
}
public void Save()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class MyClass
{
}

How to Implement Repository FindAll() Method?

I have the following Repository Pattern. Requirement is to “Find All accounts whose owner’s name is Lijo”. So, I need to write a FindAll function. How to write this function?
Constraints are:
1) The client “BankAccountService” should not use classes from 'DBML_Project'.
2) We should NOT use GetAll method to retireve complete list of accounts and then do a filter.
Note: I confronted this problem while working on the question Polymorphism: Is ORM entity a Domain Entity or Data Entity?
CODE
namespace ApplicationService_Bank
{
public class BankAccountService
{
RepositoryLayer.ILijosBankRepository accountRepository = new RepositoryLayer.LijosSimpleBankRepository();
public void FreezeAllAccountsForUser(string userName)
{
//Should not use assembly 'DBML_Project'.
IEnumerable<DomainEntitiesForBank.IBankAccount> accountsForUserWithNameLIJO = null;
//accountsForUserWithNameLIJO = accountRepository.FindAll(p => p.BankUser.Name == "Lijo");
}
}
}
namespace RepositoryLayer
{
public interface ILijosBankRepository
{
List<DomainEntitiesForBank.IBankAccount> GetAll();
IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate);
void SubmitChanges();
}
public class LijosSimpleBankRepository : ILijosBankRepository
{
private IBankAccountFactory bankFactory = new MySimpleBankAccountFactory();
public System.Data.Linq.DataContext Context
{
get;
set;
}
public virtual List<DomainEntitiesForBank.IBankAccount> GetAll()
{
List<DBML_Project.BankAccount> allItems = Context.GetTable<DBML_Project.BankAccount>().ToList();
List<DomainEntitiesForBank.IBankAccount> bankAccounts = new List<DomainEntitiesForBank.IBankAccount>();
foreach (DBML_Project.BankAccount acc in allItems)
{
DomainEntitiesForBank.IBankAccount theAccount = bankFactory.CreateAccount(acc.AccountType, acc.BankAccountID, acc.Status, acc.OpenedDate, acc.AccountOwnerID);
bankAccounts.Add(theAccount);
}
return bankAccounts;
}
public IEnumerable<DBML_Project.BankAccount> FindAll(System.Func<DBML_Project.BankAccount, bool> predicate)
{
//Where
var results = Context.GetTable<DBML_Project.BankAccount>().Where(predicate);
return results;
}
public virtual void SubmitChanges()
{
Context.SubmitChanges();
}
}
}
READING:
Returning IEnumerable<T> vs. IQueryable<T>
how to design Repository pattern to be easy switch to another ORM later?
A simple approach is to just build the query by hand:
public class SearchCriteria
{
public string Name { get; set; }
// ...more
}
public IEnumerable<Entity> FindAll(SearchCriteria criteria)
{
IQueryable<Entity> entities = _datasource.Entities; // replace with your L2S equivalent
if (criteria.Name != null)
entities = entities.Where(e => e.Name == criteria.Name);
// ...more
return entities;
}
If you don't want to return the generated objects directly, map to something else before you return:
return Map(entities); // IEnumerable<CustomObject> Map(IEnumerable<Entity> entities)

Categories