I'm developing an application with .NET Core and EF. I'm trying to implement some unit test using FakeItEasy and NUnit. Here's my problem.
I've a DbContext as this one:
public class PostgresDbContext : IdentityDbContext<User, IdentityRole<int>, int> {
// Add DbSets
public virtual DbSet<Institution> Institutions { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
...
Then I've a repository that uses PostgresDbContext:
public class UserRepository {
private readonly PostgresDbContext _dbContext;
public UserRepository(PostgresDbContext dbContext) {
_dbContext = dbContext;
}
...
And finally I've a service (the class that I'm trying to test) which uses UserRepository.
public class AuthService : BaseServiceAbstract {
private readonly SignInManager<User> _signInManager;
private readonly UserRepository _userRepository;
public AuthService(SignInManager<User> signInManager, UserRepository userRepository) {
_signInManager = signInManager;
_userRepository = userRepository;
}
The problem is when I try to Mock UserRepository in the following method:
[Test, Description("Should login when provided with right credentials")]
public void Login() {
var user = new Employee {Name = "user"};
var signInManger = A.Fake<SignInManager<User>>();
var userRepository = A.Fake<UserRepository>();
_authService = new AuthService(signInManger, userRepository);
A.CallTo(() => userRepository.FindUserByUsername("user"))
.Returns(user);
_authService.Login("user", "password");
}
I throws me the error:
FakeItEasy.Core.FakeCreationException :
Failed to create fake of type DAL.Repositories.UserRepository:
The constructors with the following signatures were not tried:
(*DAL.PostgresDbContext)
Types marked with * could not be resolved. Please provide a Dummy Factory to enable these constructors.
Any idea?
To create a fake UserRepository, FakeItEasy needs an instance of PostgresDbContext. So it tries to create a fake one, but doesn't succeed (I don't have enough details to determine why exactly). Anyway, mocking a DbContext is always difficult.
Instead of mocking UserRepository directly, consider introducing a IUserRepository interface, implemented by UserRepository, and inject that in your AuthService. Mocking interfaces is generally much easier than mocking classes.
In general, you should avoid making your classes depend on other concrete classes. They should depend on abstractions instead. This will make your life much easier when writing unit tests.
Related
I am new to unit testing and I have been using the CQRS mediatR pattern. I want to add unit tests for GetAllAsync() and GetByGameNameAsync() methods using Moq and xUnit. The code runs fine as intended but I need unit testing for it.
There is no connected database, I need to be able to write tests that will check both GetAllAsync() and GetByGameNameAsync() methods to see if it is working as intended.
How can i use inmemoryDb to write tests for the two methods?
public class IGenericRepository<TContext, TEntity> : IGenericRepository<TEntity>
where TContext: DbContext
where TEntity: class
{
private readonly TContext _gameDbContext;
private readonly DbSet<TEntity> _gameDbSet;
public IGenericRepository(TContext dbContext)
{
_gameDbContext = dbContext;
_gameDbSet = dbContext.Set<TEntity>();
}
public async Task<IReadOnlyList<TEntity>> GetAllAsync()
{
var getBack = await _gameDbSet.ToListAsync();
return getBack;
}
GameDbContext.cs
public class GamesDbContext : DbContext
{
public GameDbContext(DbContextOptions<GamesDbContext> options) :base(options)
{
}
public DbSet<GamesEntity> GamesEntity => Set<GamesEntity>():
GamesEntity.cs
public int Id {get; set;}
public string gameName {get; set;} =null!;
public string gameDescription {get; set;}=null!;
GamesRepository.cs
public class GamesRepository: GenericRepository<GamesDbContext, GamesEntity>, IGamesRepository
{
private readonly GamesDbContext _gamesDbContext;
private readomly GamesDbSet<GamesEntity> _gamesDbSet;
public GamesRepository( GamesDbContext dbContext) : base(dbContext)
{
_gamesDbContext - dbContext;
_gamesDbSet = dbContext.Set<GamesEntity>();
}
public async Task<ReadOnlyList<GamesEntity>> GetByGameNameAsync(string gameName)
{
var gameEntities = await _gamesDbContext.GamesEntity.
Where(v => v.Entity == gameName)
.ToListAsync();
return gameEntities;
}
With such an organization of the code, there is no way to make unit tests, since mocking DbContext is a practically impossible and, most importantly, useless task.
The repository itself does not contain complex business logic, and covering it with tests does not bring any benefit.
If you still need to write tests, then you can use In-Memory DB, although there are many opponents of this approach.
Im going through a tutorial which uses EF 6 and a UnitOfWork pattern. The idea is to introduce Autofac and im not entirely sure how i should convert this line of code so it fits in with the project to introduce Dependency Injection
private readonly ContactsContext _context;
public UnitOfWork(ContactsContext context)
{
_context = context;
Customers = new CustomerRepository(_context);
}
public ICustomerRepository Customers { get; }
I can't change
Customers = new CustomerRepository(_context);
to
Customers = new ICustomerRepository(_context);
Note the Interface as it throws an error.
I can post the ICustomerRepository if required but I don't know how I should be handling the dependency in this case?
I can post more code if required but I didn't know if this is enough and I'm missing something simple or not?
The standard way to do this would be to take a constructor dependency on ICustomerRepository instead of instantiating a CustomerRepository yourself within the constructor:
private readonly ContactsContext _context;
public UnitOfWork(ContactsContext context, ICustomerRepository customerRepository)
{
_context = context;
Customers = customerRepository;
}
public ICustomerRepository Customers { get; }
Of course, you will also need to register CustomerRepository with Autofac as the implementation of ICustomerRepository.
builder.RegisterType<CustomerRepository>().As<ICustomerRepository>();
This means that you will be relying on Autofac to create the repository instead of doing so yourself (Autofac will 'know' to inject the ContactsContext into the constructor of CustomerRepository). That's the pervasive aspect of dependency injection - it ends up requiring you to adopt it all the way down.
Situation
Here I am, trying to write some unit tests for my GroupService with the use of MOQ.
To create an instance of my GroupService, I mocked 4 interfaces that needed to be passed through the constructor. Now on one of the mocks (IGroupRepository) a property called Context is called and my idea was to SetupGet this property and just simply return a fake list of GroupUser. But I keep getting errors, whatever I try.
Code
public class GroupServiceTests
{
private readonly GroupService _groupService;
private readonly Mock<AppDbContext> _dbContext;
private readonly Mock<IGroupRepository> _groupRepository;
private readonly Mock<IComponentService> _componentService;
private readonly Mock<IUserContextService> _userContextService;
private readonly Mock<IModelEntityMapper<Group, Core.DbContexts.Entities.Group>> _mapper;
public GroupServiceTests()
{
var groupUsersMock = CreateDbSetMock(GetFakeListOfGroupUsers());
_dbContext = new Mock<AppDbContext>(new DbContextOptions<AppDbContext>());
_dbContext.SetupGet(x => x.GroupUser).Returns(groupUsersMock.Object);
_groupRepository = new Mock<IGroupRepository>();
_groupRepository.SetupGet(repo => repo.Context).Returns(_dbContext.Object);
_componentService = new Mock<IComponentService>();
_userContextService = new Mock<IUserContextService>();
_mapper = new Mock<IModelEntityMapper<Group, Core.DbContexts.Entities.Group>>();
_groupService = new GroupService(_groupRepository.Object, _componentService.Object, _userContextService.Object, _mapper.Object);
}
}
In the GroupService this line is called:
// _repository reffers to IGroupRepository
userIdsForContextReset.AddRange(_repository.Context.GroupUser.Where(x => groupIds.Contains(x.GroupId)).Select(x => x.UserId));
And the GroupRepository and EntityRepository look like this:
public interface IGroupRepository : IEntityRepository<AppDbContext, Group>
{
List<GroupPermission> GetInheritedGroupPermissions(int groupId);
}
public class GroupRepository : EntityRepository<AppDbContext, Group>, IGroupRepository
{
public GroupRepository(AppDbContext dbContext) : base(dbContext)
{
}
public List<GroupPermission> GetInheritedGroupPermissions(int groupId)
{
// Removed for brevity
}
}
public class EntityRepository<TDbContext, TEntity> : EntityRepository<TDbContext, TEntity, int>, IEntityRepository<TDbContext, TEntity>
where TDbContext : DbContext
where TEntity : class, IEntity<int>
{
public EntityRepository(TDbContext dbContext) : base(dbContext)
{
}
}
public class EntityRepository<TDbContext, TEntity, TId> : IEntityRepository<TDbContext, TEntity, TId>
where TDbContext : DbContext
where TEntity : class, IEntity<TId>
where TId : IComparable
{
public EntityRepository(TDbContext context)
{
Context = context;
}
public TDbContext Context { get; }
}
And last but not least, the AppDbContext and SqlDbContext:
public class AppDbContext : Shared.DbContexts.SqlDbContext
{
public virtual DbSet<GroupUser> GroupUser { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
}
public class SqlDbContext : DbContext
{
public SqlDbContext(DbContextOptions options) : base(options)
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
ChangeTracker.StateChanged += ChangeTracker_StateChanged;
}
}
Error
The error that I am getting is inside the SqlDbContext on the 1st line inside the constructor and says the following:
System.InvalidOperationException: 'No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.'
What am I doing wrong?
When you mock an implementation it creates the object using the constructor matching the parameters provided; it runs that code.
Additionally, anything not able to be mocked (not virtual or abstract) will run as is. In this case, you're passing in DbContextOptions and you haven't specified a provider, and something needs that.
This can be an opinionated topic, however to solve your problem there are a number of ways you could do it:
Add a parameterless constructor to your DbContext for testing. I wouldn't recommend this as I follow the mantra of not changing your SUT for a test.
Use an in-memory provider; EF Core In-Memory Database Provider or SQLite EF Core Database Provider are two that I have used. They do have limitations but for the OP usage would probably be fine and addresses Microsofts notes about how you shouldn't mock the DbContext.
Use an existing library such as EntityFrameworkCore.Testing (disclaimer, I am the author) which will extend in-memory providers to address their limitations.
Is it good to resolve the dependencies dynamically like the way i'm doing. Everywhere, it is suggested to use Constructor injection. I really don't understand the drawbacks of doing it the way i'm doing it. Code snippets as below..
Employee.cs
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Department Department { get; set; }
}
IRepository.cs
public interface IRepository<TModel> where TModel : class
{
void Add();
IEnumerable<TModel> GetAll();
IEnumerable<TModel> GetByID();
}
Repository.cs
public class Repository<TModel> : IRepository<TModel> where TModel : class
{
public void Add()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetAll()
{
throw new NotImplementedException();
}
public IEnumerable<TModel> GetByID()
{
throw new NotImplementedException();
}
}
EmployeeController.cs
public class HomeController : ApiController
{
IComponentContext _container;
public HomeController(IComponentContext container)
{
this._container = container;
}
public Repository<TModel> Using<TModel>() where TModel :class
{
var repository = _container.Resolve(typeof(IRepository<TModel>));
return repository as Repository<TModel>;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return Using<Employee>().GetAll();
}
}
Global.asax
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
var container = builder.Build(Autofac.Builder.ContainerBuildOptions.None);
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
}
Say i've 5 repositories, Constructor injection will resolve all the 5 dependencies for a request i make. I might not use 5 repositories for each and every request. SO i thought of resolving dependencies dynamically by passing the type like i'm doing it in Using<TModel>(). Any suggestions would be appreciated..!! Thank you...!!
Refrain from using the container directly inside your application components; this leads to all kinds of troubles such as maintainability and testability issues. Directly resolving instances from within application code is a well-known anti-pattern known as Service Locator.
As a first refactoring, you can instead apply the Unit of Work pattern. A Unit of Work allows access to underlying repositories. For instance:
public interface IUnitOfWork
{
IRepository<TModel> Repository<TModel>();
}
public sealed class HomeController : ApiController
{
private readonly IUnitOfWork _unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._unitOfWork.Repository<Employee>().GetAll();
}
}
Within the Composition Root (where it is allowed to access the container), we can now create an IUnitOfWork implementation that resolves repositories dynamically:
private sealed class AutofacUnitOfWork : IUnitOfWork
{
private readonly IComponentContext _container;
public AutofacUnitOfWork(IComponentContext container)
{
this._container = container;
}
public IRepository<TModel> Repository<TModel>()
{
return _container.Resolve<IRepository<TModel>>();
}
}
This pattern simplifies your application components considerably and prevents downsides that the Service Locator anti-pattern typically causes.
Although applying the Unit of Work pattern might be a useful step into the right direction, an even better approach is to skip the Unit of Work directly and simply inject a required repository directly into application components:
public sealed class HomeController : ApiController
{
private readonly IRepository<Employee> _employeeRepository;
public HomeController(IRepository<Employee> employeeRepository)
{
this._employeeRepository = employeeRepository;
}
[HttpGet]
public IEnumerable<Employee> GetEmployees()
{
return this._employeeRepository.GetAll();
}
}
Say i've 5 repositories, Constructor injection will resolve all the 5 dependencies for a request i make. I might not use 5 repositories for each and every request.
Note that from a performance perspective, you should typically not be concerned whether dependencies are used or not. Autofac is in most cases fast enough and it is unlikely that this will actually cause any performance problems in your production systems.
From a design perspective however you should be more worried if a class has many dependencies, while methods just use a few of them. This means that the methods in the class have little cohesion. This is an indication that the class should be split up into multiple smaller classes; it has multiple responsibilities.
i am about to learn IoC and Dependency Injection. And i am wondering if i understood the priciple an the pattern right.
I try to implement a UnitOfWork / Repository Pattern. I want two implementations of my Repository Classes for Unit Testing, and i want the UnitOfWork to "decide" which Concrete Implementation to instantiate (with the Help of Unity).
Example
The IUserRepository Interface
public interface IUserRepository
{
List<User> getAll();
}
The Repository Implementation using real data
public class UserRepository : IUserRepository
{
private MyDbContext db;
public UserRepository(MyDbContext db)
{
this.db = db;
}
public List<DomainModel.User> getAll()
{
return db.Users.ToList();
}
}
The FakeRepository Implementation
public class FakeUserRepository : IUserRepository
{
private List<User> userSet;
public FakeUserRepository()
{
// Fake Data
userSet = new List<User>();
userSet.Add(new User { Username = "john", Active = true, EMail = "john#ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "ashley", Active = true, EMail = "ashley#ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "kaidan", Active = true, EMail = "kaidan#ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "tali", Active = true, EMail = "tali#ann.net", Password = "supersecret" });
}
public List<DomainModel.User> getAll()
{
return userSet;
}
}
My UnitOfWork Implementation using Unity
// To Keep it simple, i skipped the IDisposable part ;)
public class UnitOfWork
{
MyDbContext db;
private IUserRepository userRepository;
UnityContainer container = new UnityContainer();
public UnitOfWork(bool fake = false)
{
if (fake)
{
container.RegisterType<IUserRepository, FakeUserRepository>();
}
else
{
db = = new MyDbContext();
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(db));
}
}
public IUserRepository UserRepository
{
get
{
if (userRepository == null)
{
userRepository = container.Resolve<IUserRepository>();
}
return userRepository;
}
}
public void Save()
{
db.SaveChanges();
}
}
Now when i call new UnitOfWork() it will give me the "UnitOfWork with RealData" Implementation. If i call new UnitOfWork(fake: true) it will give me the "UnitOfWork with Fake Data". So far so good. But is this the way Unity and DI should be used? If my Application grows to say 30 Repositories do i end up defining large "If/else" Blocks, right? And imagine a want do add more data stores like XML or WCF as Source for Data. If i continue to use it like above, i will end up with a very complex and blown UnitOfWork Class.
First: I am not sure if i understood DI and Unity as it's ment to be used. If i understood it right: would it be better to use a Factory that gives me the right Type of UnitOfWork?
Any Help or tip is very welcome.
Thanks,
Matze
I would separate the Unit of Work like you did with the repositories: an IUnitOfWork interface and concrete classes for the fake and the Entity Framework Unit of Work. The Unit of Work you have now violates the Single Responsibility Principle because it has multiple responsibilities:
Pass the save call to the Entity Framework Unit of Work
Determining if the Unit of Work is fake or real
Registering the repositories on the Unity container
If you have a separate Unit of Work for Entity Framework, you won't need the container to resolve the repositories from, but you can make them member variables which you initialize in your constructor. You only have to register the correct Unit of Work on the container.