Unit Testing Generic Methods (NUnit) - c#

I have been trying to implement the repository pattern in .Net Core using a generic class. This is what i have come up with (ive taken out all but one method to keep it simple). The class / method works, but im trying to write a unit(integration) test for it, in this case the Add Method.
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly DbContext Context;
public Repository(DbContext context)
{
Context = context;
}
public void Add(TEntity entity)
{
Context.Set<TEntity>().Add(entity);
}
}
So far my integration test is as follows,
Set Up makes a SqlLite database to save to
Sets up the DbContext
Sets up a Unit of Work - The unit of work is needed to SaveChanges the the DbContext and can be ignored for the most part
Then im creating a "StorageSystem" Domain Object and testing the Generic class. But it feels like I should be able to test it with out passing a specific domain model. Or at the very least, enter the different domain models as parameterised tests.
[TestFixture]
public class RepositoryTests
{
SqliteConnection _connection;
DbContextOptions<ApplicationDbContext> _options;
ApplicationDbContext _context;
UnitOfWork _uow;
[SetUp]
public void SetUp()
{
_connection = new SqliteConnection("DataSource=:memory:");
_connection.Open();
_options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseSqlite(_connection)
.Options;
using (var context = new ApplicationDbContext(_options))
{
context.Database.EnsureCreated();
}
_context = new ApplicationDbContext(_options);
_uow = new UnitOfWork(_context);
}
[TearDown]
public void TearDown()
{
_connection.Close();
}
[Test]
public void Add_AddsEntityToRepository()
{
//arrange
var storageSystem = new StorageSystem {Id = 1, Name = "Storage1"};
var repo = new Repository<StorageSystem>(_context);
//act
repo.Add(storageSystem);
_uow.Complete();
//assert
Assert.AreEqual(1, _context.StorageSystems.Count());
}
I am fairly new to working with Generics, The closest solution I could find was using an abstract class. However I couldnt make it working with me code with it not detecting the tests as an abstract class and not being able to make a repository of type TEntity.
Example taken from here
[TestFixture]
public abstract class RepositoryTests1<TEntity>
{
SqliteConnection _connection;
DbContextOptions<ApplicationDbContext> _options;
ApplicationDbContext _context;
UnitOfWork _uow;
[SetUp]
public void SetUp()
{
_connection = new SqliteConnection("DataSource=:memory:");
_connection.Open();
_options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseSqlite(_connection)
.Options;
using (var context = new ApplicationDbContext(_options))
{
context.Database.EnsureCreated();
}
_context = new ApplicationDbContext(_options);
_uow = new UnitOfWork(_context);
}
[TearDown]
public void TearDown()
{
_connection.Close();
}
[Test]
public void Add_AddsEntityToRepository_GenericAttempt()
{
//arrange
TEntity entityToAdd = this.CreateEntity();
var repo = new Repository<TEntity>(_context); //ERROR HERE - TEntity must be a reference type
//act
repo.Add(entityToAdd);
_uow.Complete();
//assert
//NO IDEA WHAT THE ASSERTION WOULD BE
}
protected abstract TEntity CreateEntity();
}
So in short, how do i unit test this Generic Repository?

You could Restrict your Repository to a certain base class created by you like EntityBase (this should be abstract)
public class EntityBase
{
public int Id { get; set; }
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : EntityBase
{
...
}
Then you are able to pass your base type to this test methods.
[Test]
public void Add_AddsEntityToRepository()
{
//arrange
var storageSystem = new StorageSystem {Id = 1, Name = "Storage1"};
var repo = new Repository<EntityBase>(_context);
//act
repo.Add(storageSystem);
_uow.Complete();
//assert
Assert.AreEqual(1, _context.StorageSystems.Count());
}
Since you are ensuring through inherintance, that every type has at least the members of EntityBase, you do not have to test further more down the inheritance tree of your entity types. (unless you have a certain use-case for that)
If you certain methods, that you need to know on the base-type, but the implementation depends on the child class, simply put the method as abstract member in the base class and override it in the child class.
public class EntityBase
{
public int Id { get; set; }
// sample method that copies member values from other object to current instance
public abstract void CopyProperties(EntityBase other);
}
public class Student : EntityBase
{
public int Id { get; set; }
public override void CopyProperties(EntityBase other)
{
...
}
}

Related

Mocking a Service using Moq in C#

I have a service that is setup in this way.
public Interface IDataService : IDisposable
{
IQueryable<T> Set<T>() where T : class;
IDbSet<T> WritableSet<T>() where T : class;
}
IDataService is inherited by DataService.
public abstract class DataService : IDataService
{
public IDataContext DataContext { get; private set; }
public IQueryable<T> Set<T>() where T : class
{
return DataContext.Set<T>().AsNoTracking();
}
public IDbSet<T> WritableSet<T>() where T : class
{
return DataContext.Set<T>();
}
public AddResult<T> Add<T>(T obj) where T : class, IPersistentEntity
{
if (obj == null)
return new AddResult<T>() { IsValid = false };
else
{
if (obj.Id == Guid.Empty)
WritableSet<T>().Add(obj);
bool success = DataContext.SaveChanges() > 0;
return new AddResult<T>() { Entity = obj, IsValid = success };
}
}
}
And The DataService is inherited by EntityService.
public class EntityService : DataService
{
public EntityService(IDataContext DataContext) : base(DataContext)
{
}
public void EntityStarted(Guid Id)
{
var a = GetWriteableById<Entity>(Id);
a.Status = 1;
DataContext.SaveChanges();
}
}
This EntityService is used in one of my components. EntityService's object is created and passed to the component's constructor.
I'm using Moq to perform some tests on the component and for that, the plan was to mock the EntityService such that the EntityService uses a fake db container with dummy data for database like operations. But, I'm not having the best idea to mock this with minimum amount of new code.
The least appealing idea that I have is to create a fake EntityService class using the interface and have it's own implementation suitable for tests.
Help is appreciated! :)
As per #JLe and #Chetan's comment on the question, I had to mock the DbContext.
I followed this article to mock the DbContext.
Mocking DbContext with Moq
Here is how the code looks like.
private void Setup()
{
List<Entity> entityData = new List<Entity>();
entityData.Add(new Entity
{
Id = Guid.NewGuid()
});
DbSet<Entity> MockEntitySet = GetSet(entityData);
MockContext = new Mock<IDbContext>();
MockContext.Setup(m => m.Set<Entity>()).Returns(MockEntitySet);
}
public static DbSet<T> GetSet<T>(List<T> sourceList) where T : class
{
return GetSet(sourceList.ToArray());
}
public static DbSet<T> GetSet<T>(T[] sourceList) where T : class
{
var name = typeof(T).Name;
var queryable = sourceList.AsQueryable();
Mock<DbSet<T>> dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
dbSet.Setup(m => m.AsNoTracking()).Returns(dbSet.Object);
return dbSet.Object;
}
[TestMethod]
public void Test()
{
EntityService service = new EntityService(MockContext.Object);
ComponentToTest compObj = new ComponentToTest(service);
compObj.MethodToTest(...);
// Assertions
}
Thank you guys! Appreciate your help and suggestions.
To mock you need an Interface, if not, you need to mark the methods that you want to mock as virtual.
Under the hood the mocking framework is going to create a new implementation for you that behaves as you configured the mock.
Hope it helps.

Moq - Update with DbEntityEntry

I'm using EF6. The generated code is something like:
public partial class MyDataContext : DbContext
{
public MyDataContext() : base("name=mydata")
{
}
public virtual DbSet<Book> Books { get; set; }
}
Then I have a generic repository like:
public class GenericRepository<TObject> where TObject : class
{
protected readonly MyDataContext Context;
protected GenericRepository(MyDataContext context)
{
Context = context;
}
public virtual TObject Update(TObject data, int id)
{
if (data == null)
return null;
TObject obj = Context.Set<TObject>().Find(id);
if (obj != null)
{
Context.Entry(obj).CurrentValues.SetValues(data);
Context.SaveChanges();
}
return obj;
}
}
Then I have a service that uses the GenericRepository to update data:
public class MyDataService<TObject> where TObject : class
{
private readonly MyDataContext context;
public MyDataService(MyDataContext ct)
{
context = ct;
}
public TObject Update(TObject obj, int id)
{
var r = new GenericRepository<TObject>(context);
return r.Update(obj, id);
}
}
So I can update a books with something like this:
var ds = new MyDataService<Book>(new MyDataContext());
var data = ds.Update(new Book { Name = "New Name" }, 1);
This is working fine. Next I try to use Moq to unit test the above code with something like:
var updatedBook = new Book { Name = "Update Book Name" };
var mockSet = new Mock<DbSet<Book>>();
var mockContext = new Mock<MyDataContext>();
mockContext.Setup(c => c.Books).Returns(mockSet.Object);
mockContext.Setup(c => c.Set<Book>().Find(It.IsAny<object[]>()))
.Returns<object[]>(ids => chips.FirstOrDefault(d => d.Id == (int)ids[0]));
var service = new MyDataService<Book>(mockContext.Object);
var data = service.Update(updatedBook, 1);
However, I get an exception on the Context.Entry(obj).CurrentValues.SetValues(data) line.
How do I mock the Update method properly?
You could implement an interface for MyDataService to be able to mock it
public Interface IMyDataService<TObject> where TObject : class
{
TObject Update(TObject obj, int id);
}
public class MyDataService<TObject>:IMyDataService<TObject>
where TObject : class
{
private readonly MyDataContext context;
public MyDataService(MyDataContext ct)
{
context = ct;
}
public TObject Update(TObject obj, int id)
{
var r = new GenericRepository<TObject>(context);
return r.Update(obj, id);
}
}
Moq:
var mockDataService = new Mock<IMyDataService<Book>>();
mockDataService.Setup(c=> c.Update(It.Any<Book>(),It.Any<int>()).Returns(updatedbook);
The service should be dependent on the repository. Passing the context directly to the service is misleading as what the service really needs and uses is the repository.
Your classes should depend on abstractions and not on concretions. That said, all the above classes could be abstracted behind interfaces. but for now I'll focus on the service class and it's dependence on the repository. You are coupling different layers too closely. Service layer doesn't need to know about data context
Abstract the repository to allow for easier testability
interface IGenericRepository<TObject> where TObject : class {
TObject Update(TObject data, int id);
}
public class GenericRepository<TObject> : IGenericRepository<TObject> where TObject : class {
protected readonly MyDataContext Context;
public GenericRepository(MyDataContext context) {
Context = context;
}
public virtual TObject Update(TObject data, int id) {
if (data == null)
return null;
TObject obj = Context.Set<TObject>().Find(id);
if (obj != null) {
Context.Entry(obj).CurrentValues.SetValues(data);
Context.SaveChanges();
}
return obj;
}
}
The service would only now need to know about the repository abstraction, not its implementation details.
public class MyDataService<TObject> where TObject : class {
private readonly IGenericRepository<TObject> repository;
public MyDataService(IGenericRepository<TObject> repository) {
this.repository = repository;
}
public TObject Update(TObject obj, int id) {
return repository.Update(obj, id);
}
}
So now the service can be tested in isolation without any need to worry about any data context
//Arrange
var updatedBook = new Book { Name = "Update Book Name" };
var id = 1;
var mockRepository = new Mock<IGenericRepository<Book>>();
mockRepository
.Setup(m => m.Update(updatedBook, id))
.Returns(updatedBook);
var service = new MyDataService<Book>(mockRepository.Object);
//Act
var data = service.Update(updatedBook, id);
//Assert
//...
When it's time to unit test the repository implementation in isolation, then you can follow the same structure and abstract the context for the repository implementation.
I would suggest the small refactoring in order to make the testing easier and even possible. With this implementation you are relying on the implementation of the DbContext and DbEntityEntry.
At first extract interface for your context:
public inteface IMyDataContext<TObject> where TObject is class
{
TObject FindById(int id); //call FindId
void Update(TObject); //call DbEntityEntry SetValues
void SaveChanges();
}
In the GenericRepository then inject the interface. This will make your life easier, you can then easily mock all method. Unit tests of the repository should verify that right methods of the context are called.

Am I testing My repository the right way?

I have a generic Repository like this:
public interface IRepository<TEntity> where TEntity :class
{
IEnumerable<TEntity> SearchFor(Expression<Func<TEntity, bool>> filter);
TEntity GetById(int id);
void Insert(TEntity entity);
void Delete(TEntity entity);
void Update(TEntity entity);
}
public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity: class
{
private DbSet<TEntity> _dbSet; // put the entity specified in place of TEntity in d DbSet so i can query the entity e.g School Entity
private NaijaSchoolsContext _naijaSchoolsContext;
public GenericRepository(NaijaSchoolsContext context)
{
_naijaSchoolsContext = context;
_dbSet = _naijaSchoolsContext.Set<TEntity>(); //return the entity specified in the TEntity and put it in DbSet
}
public IEnumerable<TEntity> SearchFor(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter)
{
return _dbSet.Where(filter);
}
public TEntity GetById(int id)
{
return _dbSet.Find(id);
}
public void Insert(TEntity entity)
{
_dbSet.Add(entity);
}
public void Delete(TEntity entity)
{
_dbSet.Remove(entity);
}
public void Update(TEntity entity)
{
_dbSet.AddOrUpdate(entity);
}
}
I also have a UoW like this:
public interface IUnitofWork : IDisposable
{
void Save();
}
public class UnitofWork : IUnitofWork
{
NaijaSchoolsContext naijaSchoolsContext = new NaijaSchoolsContext();
private GenericRepository<School> schoolRepository;
private bool isDisposed = false;
public GenericRepository<School> SchoolRepository
{
get
{
if (schoolRepository == null)
{
schoolRepository = new GenericRepository<School>(naijaSchoolsContext);
}
return schoolRepository;
}
}
public void Save()
{
naijaSchoolsContext.SaveChanges();
}
public void Dispose(bool disposing)
{
if (!isDisposed)
{
if (disposing)
{
naijaSchoolsContext.Dispose();
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
My test class looks like this:
[TestFixture]
public class when_working_with_school_repository
{
}
public class and_saving_a_school : when_working_with_school_repository
{
private School _returnedSchool;
private School _school;
private Mock<IRepository<School>> _repository;
private Exception _result;
[SetUp]
private void SetUp()
{
_repository = new Mock<IRepository<School>>();
_school = new School();
}
[Test]
public void then_a_valid_school_should_be_saved()
{
_repository.Setup(s => s.Insert(_school));
//_returnedSchool = _schoolRepository.Save(_school);
}
[Test]
public void should_throw_an_exception_when_no_school_is_saved()
{
try
{
_repository.Setup(s => s.Insert(null));
}
catch (Exception exception)
{
_result = exception;
}
}
[Test]
public void should_notify_user_if_school_name_already_exists()
{
//bool exists = _schoolRepository.IsExist(_school.Name);
}
}
My tests passes but my concern is that
Am I not supposed to mock the UnitOfWork class. When I tried mocking it, i couldn't get to the StudentRepository class. In using the code without tests, I would have to instantiate UoW to perform my actions, that is why i asked if am supposed to Mock my UoW. if am to Mock it how can i do that?
Please help me if my test is correct or I need to take another course of action.
No, you are not. You are testing mock:
_repository = new Mock<IRepository<School>>();
You want to test your code, not others. Your generic repository simply delegates calls to _dbSet. And that's what you want to test - that calls are delegated (this is sort of wrapper-functionality).
How to do that? You need abstraction over DbSet<T> and this is the object you mock in test. All your tests will look similar:
var dbSetMock = new Mock<DbSet<School>>();
var context = new Mock<Context>();
var repository = new GenericRepository<School>(dbSetMock, context);
repository.FindBy(arg);
dbSetMock.Verify(d => d.FindBy(arg));
This requires abstraction over both DbSet and your custom context to make it work.
I think you're better of mocking the IRepository. But, your test will pass because your not asserting for anything.
I think you need to setup your your mock inorder to get the desired result. Here is a modified example:
[Test]
public void then_a_valid_school_should_be_saved()
{
var _school = new School { .... };
var expected = _school.Id;
_repository.Setup(s => s.Insert(_school));
_repository.Setup(s => s.GetById(_school.Id)).Returns(_school);;
_repository.Insert(_school);
var actual = _repository.GetById(_school.Id);
Assert.Equal(expected, actual);
}
That should do it. To make the test fail try putting a different Id for the expected result and verify that it works. You can use that to improve upon your other test.

Registering different UnitOfWorks per each module for a generic CommandHandler using structuremap

I'm using CQRS pattern in my recent project, and used EF code first in my DAL, so I defined some generic CommandHandlers to do Insert/Update/Delete:
public class InsertCommandHandler<TEntity> : ICommandHandler<InsertCommandParameter<TEntity>>
where TEntity : BaseEntity, IAggregateRoot<TEntity>, new()
{
private readonly IUnitOfWork _uow;
public InsertCommandHandler(IUnitOfWork uow)
{
_uow = uow;
}
public void Handle(InsertCommandParameter<TEntity> parameter)
{
var entity = parameter.Entity;
_uow.Repository<TEntity>().Add(entity);
}
}
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : ICommandParameter
where T : BaseEntity, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T> where T : class, new()
{
}
As you see I injected the IUnitOfWork to the InsertCommandHandler constructor.
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : BaseEntity, IAggregateRoot<T>,new ();
void Commit();
}
I used Structuremap 3 as my IoC Container, So I defined following conversion to resolve ICommandHandlers for each BaseEntity types(using custom registration conventions for partially closed types):
public class CRUDCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention
{
private static readonly
Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly
Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly
Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
private static readonly
Type _openUpdateCommandType = typeof(UpdateCommandParameter<>);
private static readonly
Type _openUpdateCommandHandlerType = typeof(UpdateCommandHandler<>);
private static readonly
Type _openDeleteCommandType = typeof(DeleteCommandParameter<>);
private static readonly
Type _openDeleteCommandHandlerType = typeof(DeleteCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type))
if (type.GetInterfaces()
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition()
== typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
Type closedUpdateCommandType = _openUpdateCommandType.MakeGenericType(type);
Type closedUpdateCommandHandlerType = _openUpdateCommandHandlerType.MakeGenericType(type);
Type closedDeleteCommandType = _openDeleteCommandType.MakeGenericType(type);
Type closedDeleteCommandHandlerType = _openDeleteCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
Type updateclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedUpdateCommandType);
Type deleteclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(closedDeleteCommandType);
registry.For(insertclosedHandlerInterfaceType).Use(closedInsertCommandHandlerType);
registry.For(updateclosedHandlerInterfaceType).Use(closedUpdateCommandHandlerType);
registry.For(deleteclosedHandlerInterfaceType).Use(closedDeleteCommandHandlerType);
}
}
}
And used it in my CompositionRoot:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType(typeof(ICommandHandler<>));
s.AssemblyContainingType(typeof(Order));
s.AssemblyContainingType(typeof(FindOrderByIdQueryHandler));
s.WithDefaultConventions();
x.For(typeof(IUnitOfWork))
.Use(typeof(EfUnitOfWork<SaleDBContext>))
.Named("SaleDBContext")
.SetLifecycleTo((Lifecycles.Singleton));
s.Convention<CRUDCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
}
I registered EfUnitOfWork<SaleDBContext> for IUnitOfWork, but I want to use separate DbContext per each module in my solution(Bounded context). For example my sale module has its own DbContext, HR module has its own DbContext and etc, and above registration conversion, only register EfUnitOfWork<SaleDBContext> as my IUnitOfWork.
I have some modules(Solution Folders in Visual Studio) in my solution and each module has 3 layer(3 class library projects):
My modules has following structure(each module has 3 assemblies) for example:
SaleModule:
----Application
----Domain (Entities , ...) //Order, Customer,...
----DAL (DbContext ,...) //SaleDbContext
HRModule:
----Application
----Domain (Entities , ...) // Employee, OrganizationUnit, ...
----DAL (DbContext ,...)//HRDbContext
InfrastructureModule:
----Application (ICommandHandler,IQueryHandler,...)
----Domain
----DAL
The InsertCommandHandler<T> puts in Infrastructure Module.
When I use the InsertCommanHandler<T> I want it uses corresponding module's DbContext as IUnitOfWork. for example, I want the InsertCommandHandler<Order> uses SaleDbContext as it's IUnitOfWork and InsertCommandHandler<Employee> uses HRDbContext as it's IUnitOfWork.
[UPDATED]
This is a sample of cunsumers code that IoC containar should provide SaleDbContext for Consumer1 and HRDbContext for Consumer2:
public class Consumer1
{
ICommandHandler<InsertCommandParameter<Order>> _insertCommandHandler;
public Consumer1(ICommandHandler<InsertCommandParameter<Order>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Order>();
command.Entity = new Order(){
Number = 'ord-01',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use SaleDbContext
}
}
public class Consumer2
{
ICommandHandler<InsertCommandParameter<Employee>> _insertCommandHandler;
public Consumer2(ICommandHandler<InsertCommandParameter<Employee>> insertCommandHandler)
{
_insertCommandHandler = insertCommandHandler;
}
public void DoInsert()
{
var command = new InsertCommandParameter<Employee>();
command.Entity = new Employee(){
EmployeeNumber = 'Emp1',
// other properties
};
insertCommandHandler.Handle(command); //this query handler should use HRDbContext
}
}
How could I do that in my composition root using StructureMap?
You can make IUnitOfWork generic as in IUnitOfWork<TConnection>. This allows each Repository to stipulate which UnitOfWork it requires, ideally using constructor injection, e.g.
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesDbContext> salesUnitOfWork)
{
// ...
}
}
However, you probably don't want to reference the DbContext in each handler so you should define an abstraction to avoid such a dependency.
Start with a simple interface that all DbContext wrapper classes will implement
public interface IConnection
{
DbContext Context { get; }
}
Update IUnitOfWork accordingly
public interface IUnitOfWork<TConnection> where TConnection : IConnection { }
Here's an example wrapper
public class SalesConnection : IConnection
{
private readonly DbContext context;
public SalesConnection()
{
this.context = new SalesDbContext();
}
public DbContext Context { get { return this.context; } }
}
And here's what the updated command handler will look like
public class InsertCommandHandler : ICommandHandler<Order>
{
public InsertCommandHandler(IUnitOfWork<SalesConnection> salesUnitOfWork)
{
// ...
}
}
UPDATE
The logical thing to do for common handlers is to have one per logical domain (i.e. per DbContext), for example SalesInsertCommandHandler, HRInsertCommandHandler
public class SalesInsertCommandHandler<TCommand> : ICommandHandler<TCommand>
{
public SalesInsertCommandHandler(IUnitOfWork<SalesConnection> unitOfWork)
{
}
}
This adheres to the separation of concerns principle and gives you extra flexibility when you come to decorate your concerns with different aspects (tracing, retry logic etc.)
All command handlers can of course inherit from a single common (abstract) command handler.
public abstract class CommandHandler<TConnection, TCommand> :
ICommandHandler<TCommand>
where TConnection : IConnection
{
private readonly IUnitOfWork<TConnection> unitOfWork;
public CommandHandler(IUnitOfWork<TConnection> unitOfWork)
{
this.unitOfWork = unitOfWork;
}
}
public class SalesInsertCommandHandler<TCommand> :
CommandHandler<SalesConnection, TCommand>
{
}

How to mock EF 6 Async methods using JustMock?

I am trying to Mock Entity Framework 6.0.2 Async methods using JustMock. I am following testing with async queries but it is write using Moq I am trying to convert this into JustMock with help of Mock Multiple Interfaces but getting an exception :
The provider for the source IQueryable doesn't implement
IDbAsyncQueryProvider. Only providers that implement
IDbAsyncQueryProvider can be used for Entity Framework asynchronous
operations. For more details see
http://go.microsoft.com/fwlink/?LinkId=287068.
Here is my code :
var dummyData = GetEmployeeSkills();
var mockSet = Mock.Create<DbSet<EmployeeSkill>>();
(mockSet as IDbAsyncEnumerable<EmployeeSkill>).Arrange(x => x.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<EmployeeSkill>(dummyData.GetEnumerator()));
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.Provider).Returns(new TestDbAsyncQueryProvider<EmployeeSkill>(dummyData.Provider));
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.Expression).Returns(dummyData.Expression);
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.ElementType).Returns(dummyData.ElementType);
(mockSet as IQueryable<EmployeeSkill>).Arrange(x => x.GetEnumerator()).Returns(dummyData.GetEnumerator());
var mockContext = Mock.Create<TimeSketchContext>();
mockContext.Arrange(x => x.Set<EmployeeSkill>()).Returns(mockSet);
baseRepository = new BaseRepository<EmployeeSkill>(mockContext);
private EmployeeSkill GetEmployeeSkill()
{
return new EmployeeSkill
{
SkillDescription = "SkillDescription",
SkillName = "SkillName",
Id = 1
};
}
private IQueryable<EmployeeSkill> GetEmployeeSkills()
{
return new List<EmployeeSkill>
{
GetEmployeeSkill(),
GetEmployeeSkill(),
GetEmployeeSkill(),
}.AsQueryable();
}
Test :
[Fact]
public async Task DbTest()
{
var data = await baseRepository.FindAsync(1);
Assert.NotEqual(null, data);
}
Repository :
public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
protected readonly DbContext InnerDbContext;
protected DbSet<T> InnerDbSet;
public BaseRepository(IDbContext innerDbContext)
{
InnerDbContext = innerDbContext as DbContext;
InnerDbSet = innerDbContext.Set<T>();
}
public virtual Task<T> FindAsync(long id)
{
return InnerDbSet.FirstOrDefaultAsync(x=>x.Id == id);
}
}
Interface :
public interface IDbContext
{
DbSet<T> Set<T>() where T : class;
}
Context :
public class TimeSketchContext : DbContext, IDbContext
{
public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}
Because JustMock can mock non virtual methods when you are writing
var mockContext = Mock.Create<TimeSketchContext>();
mockContext.Arrange(x => x.Set<EmployeeSkill>()).Returns(mockSet);
it will mock the DbContext.Set<> and not your IDbContext.Set<> so you get the exception.
There are at least 2 solution to this:
Mock your IDbContext interface
var mockContext = Mock.Create<IDbContext>();
Or change back your BaseRepository to use a DbContext instead of your interface:
public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
protected readonly DbContext InnerDbContext;
protected DbSet<T> InnerDbSet;
public BaseRepository(DbContext innerDbContext)
{
InnerDbContext = innerDbContext;
InnerDbSet = InnerDbContext.Set<T>();
}
public virtual Task<T> FindAsync(long id)
{
return InnerDbSet.FirstOrDefaultAsync(x => x.Id == id);
}
}

Categories

Resources