I have a Service that uses 2 repositories and I wanna make unit tests. So for testing I need to have the constructor take interfaces instead of the repository class directly, so I can mock the repositories. But then I can't set their DbContext to the same which will lead to other problems.
Here's the code:
public class RolePrivilegeService : IRolePrivilegeService
{
private readonly RoleReadWriteRepository _roleRepo;
private readonly PrivilegeReadRepository _privilegeRead;
public RolePrivilegeService(RoleReadWriteRepository roleWrite,
PrivilegeReadRepository privilegeRead)
{
_roleRepo = roleWrite;
_privilegeRead = privilegeRead;
_roleRepo.Db = _privilegeRead.Db;
}
public async Task<int> AssignPrivilege(string roleId, string privilegeId, string companyId)
{
var role = await _roleRepo.FindRole(companyId, roleId);
if(role == null) throw new RoleNotFoundException();
var privilege = await _privilegeRead.Find(privilegeId);
if(privilege == null) throw new PrivilegeNotFoundException();
role.AssignPrivilege(privilege);
return await _roleRepo.UpdateRole(role);
}
}
The interfaces and entities are in one project and the service and repositories are in another project.
I guess from the beginning it's not the best solution to give to the service the responsibility to manage the unicity of the context.
Some possible solution (my favorite is the third one)
1) Use interfaces instead and inject DBContext (Define your strategy here, one DBContext by request if you are in api or whatever...)
2) You can anyway mock a concrete class with NSubstitute or others
3) Improve your design with having one Repository to have a better abstraction of the needed entity (Using an aggregate which is a better abstraction of your transactional boundaries)
Related
DISCLAIMER: Since we are all familiar with it, i will be using contoso university design to explain my question. Also, i am using EF core and .net core 2.0 on a mvc code first design.
I am developing a very generic RESTful API that works on any model. It has one method for each of create, read, update and delete operation in only one controller, the route of this is
[Route("/api/{resource}")]
Resource is the entity that the client wants to work with, for example if someone wants to get all Courses using the api he has to do a GET request on http://www.example.com/api/course/ or http://www.example.com/api/course/2 to get one by id and the following code will do the job.
[HttpGet("{id:int:min(1)?}")]
public IActionResult Read([FromRoute] string resource, [FromRoute] int? id)
{
//find resourse in models
IEntityType entityType = _context.Model
.GetEntityTypes()
.FirstOrDefault(x => x.Name.EndsWith($".{resource}", StringComparison.OrdinalIgnoreCase));
if (entityType == null) return NotFound(resource);
Type type = entityType.ClrType;
if (id == null)//select all from table
{
var entityRows = context.GetType().GetMethod("Set").MakeGenericMethod(type).Invoke(context, null);
if (entityRows == null)
return NoContent();
//TODO: load references (1)
return Ok(entityRows);
}
else //select by id
{
var entityRow = _context.Find(type, id);
if (entityRow == null)
return NoContent();
//TODO: load references (2)
return Ok(entityRows);
}
}
This small piece of code will do the magic with one small exception, intermediate collections will not be loaded. Given our example, the fetched course or courses will have no info for CourseInstructor (the intermediate collection in between Course and Person). I am trying to find a way to Eager load the navigation properties only if it is a collection; or by any other condition that will ensure that only many-to-many relationships are loaded.
For //TODO: load reference (2) i could use
_context.Entry(entityRow).Collection("CourseInsructor").Load();
On runtime if i could find all the navigation properties (filtered by spoken condition) and foreach of them i did Load(), i should get the desired result. My problem is when i get all (when id is null) the entityRows is type 'InternalDbSet' which is an unknown model.
So for the two TODOs i need some help on doing the following steps
1: find navigation properties of many-to-many relationships only
2: load them
Any suggestions?
In general, this seems like a very bad idea to me. While the CRUD stuff is going to be identical for most resources, there will be variances (as you've now run into). There's also something to be said for having a self-documenting API: with individual controllers, you know which resources can be accessed by nature of having a controller associated with that resource. With they way you're doing it, it's a complete black box. This also will of course effect any sort of actual generated API documentation. For example, if you were to include Swagger in your project, it would not be able to determine what you're doing here. Finally, you're now having to use reflection for everything, which will effect your performance.
What I would suggest instead is creating a base abstract controller and then creating a controller for each unique resource that inherits from that, for example:
public abstract class BaseController<TEntity> : Controller
where TEntity : class, new()
{
protected readonly MyContext _context;
public BaseController(MyContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
...
[HttpGet("create")]
public IActionResult Create()
{
var model = new TEntity();
return View(model);
}
[HttpPost("create")]
public async Task<IActionResult> Create(TEntity model)
{
if (ModelState.IsValid)
{
_context.Add(model);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(model);
}
...
}
I just wanted to give a quick example, but you'd build out all the rest of the CRUD methods in the same fashion, generically using TEntity. Then, for each actual resource, you simply do:
public class WidgetController : BaseController<Widget>
{
public WidgetController(MyContext context)
: base(context)
{
}
}
No duplication of code, but you've now got an actual real controller backing the resource, aiding both the innate and possibly explicit documentation of your API. And, no reflection anywhere.
Then, to solve problems like what you have here, you can add hooks to your base controller: essentially just virtual methods that are utilized in your base controller's CRUD actions and do nothing or just default things. However, you can then override these in your derived controllers to stub in additional functionality. For example, you can add something like:
public virtual IQueryable<TEntity> GetQueryable()
=> _context.Set<TEntity>();
Then, in your derived controller, you can do something like:
public class CourseController : BaseController<Course>
{
...
public override IQueryable<Course> GetQueryable()
=> base.GetQueryable().Include(x => x.CourseInstructors).ThenInclude(x => x.Instructor);
So, for example, you'd make your BaseController.Index action, perhaps, utilize GetQueryable() to get the list of entities to display. Simply by overriding this on the derived class, you can alter what happens based on the context of a particular type of resource.
How can I know if a class is annotated with javax.persistence.Entity?
Person (Entity)
#Entity
#Table(name = "t_person")
public class Person {
...
}
PersonManager
#Stateless
public class PersonManager {
#PersistenceContext
protected EntityManager em;
public Person findById(int id) {
Person person = this.em.find(Person.class, id);
return person;
}
I try to do it with instance of as the following
#Inject
PersonManager manager;
Object o = manager.findById(1);
o instanceof Entity // false
however the result is false, shouldn't it be true?
While the existing answers provide a (somehow) working solution, some things should be noted:
Using an approach based on Reflection implies (a) Performance Overhead and (b) Security Restrictions (see Drawbacks of Reflection).
Using an ORM-specific (here: Hibernate) approach risks portability of the code towards other execution environments, i.e., application containers or other customer-related settings.
Luckily, there is a third JPA-only way of detecting whether a certain Java class (type) is a (managed) #Entity. This approach makes use of standardized access to the javax.persistence.metamodel.MetaModel. With it you get the method
Set < EntityType > getEntities();
It only lists types annotated with #Entity AND which are detected by the current instance of EntityManager you use. With every object of EntityType it is possible to call
Class< ? > getJavaType();
For demonstration purposes, I quickly wrote a method which requires an instance of EntityManager (here: em), either injected or created ad-hoc:
private boolean isEntity(Class<?> clazz) {
boolean foundEntity = false;
Set<EntityType<?>> entities = em.getMetamodel().getEntities();
for(EntityType<?> entityType :entities) {
Class<?> entityClass = entityType.getJavaType();
if(entityClass.equals(clazz)) {
foundEntity = true;
}
}
return foundEntity;
}
You can provide such a method (either public or protected) in a central place (such as a Service class) for easy re-use by your application components. The above example shall just give a direction of what to look for aiming at a pure JPA approach.
For reference see sections 5.1.1 (page 218) and 5.1.2 (page 219f) of the JPA 2.1 specification.
Hope it helps.
If the statement
sessionFactory.getClassMetadata( HibernateProxyHelper.getClassWithoutInitializingProxy( Person.class ) ) != null;
is true, than it is an entity.
#NiVer's answer is valid. But, if you don't have a session or sessionFactory at that point you could use Reflection. Something like:
o.getClass().getAnnotation(Entity.class) != null;
I'm trying to get my head around an existing system that is built upon the UnitOfWork pattern. There are a lot of repositories that all takes an IUnitOfWork in its constructor, so that the service layers can perform multiple repository calls and then choose when to commit the changes.
The current service code may look something like this:
using (var uow = UnitOfWork.Start())
{
var orderRepository = new OrderRepository(uow);
var productRepository = new ProductRepository(uow);
orderRepository.DoSomething();
productRepository.DoSomethingElse();
uow.Persist();
}
How can I introduce true dependency injection in the service layer and still keep the UnitOfWork pattern?
I would use factory pattern. Inject factory in constructor and rewrite:
using (var uow = this.unitOfWorkFactory.Create().Start())
{
var orderRepository = new OrderRepository(uow);
var productRepository = new ProductRepository(uow);
orderRepository.DoSomething();
productRepository.DoSomethingElse();
uow.Persist();
}
Best regards
I have read dozens of posts about PROs and CONs of trying to mock \ fake EF in the business logic.
I have not yet decided what to do - but one thing I know is - I have to separate the queries from the business logic.
In this post I saw that Ladislav has answered that there are 2 good ways:
Let them be where they are and use custom extension methods, query views, mapped database views or custom defining queries to define reusable parts.
Expose every single query as method on some separate class. The method
mustn't expose IQueryable and mustn't accept Expression as parameter =
whole query logic must be wrapped in the method. But this will make
your class covering related methods much like repository (the only one
which can be mocked or faked). This implementation is close to
implementation used with stored procedures.
Which method do you think is better any why ?
Are there ANY downsides to put the queries in their own place ? (maybe losing some functionality from EF or something like that)
Do I have to encapsulate even the simplest queries like:
using (MyDbContext entities = new MyDbContext)
{
User user = entities.Users.Find(userId); // ENCAPSULATE THIS ?
// Some BL Code here
}
So I guess your main point is testability of your code, isn't it? In such case you should start by counting responsibilities of the method you want to test and than refactor your code using single responsibility pattern.
Your example code has at least three responsibilities:
Creating an object is a responsibility - context is an object. Moreover it is and object you don't want to use in your unit test so you must move its creation elsewhere.
Executing query is a responsibility. Moreover it is a responsibility you would like to avoid in your unit test.
Doing some business logic is a responsibility
To simplify testing you should refactor your code and divide those responsibilities to separate methods.
public class MyBLClass()
{
public void MyBLMethod(int userId)
{
using (IMyContext entities = GetContext())
{
User user = GetUserFromDb(entities, userId);
// Some BL Code here
}
}
protected virtual IMyContext GetContext()
{
return new MyDbContext();
}
protected virtual User GetUserFromDb(IMyDbContext entities, int userId)
{
return entities.Users.Find(userId);
}
}
Now unit testing business logic should be piece of cake because your unit test can inherit your class and fake context factory method and query execution method and become fully independent on EF.
// NUnit unit test
[TestFixture]
public class MyBLClassTest : MyBLClass
{
private class FakeContext : IMyContext
{
// Create just empty implementation of context interface
}
private User _testUser;
[Test]
public void MyBLMethod_DoSomething()
{
// Test setup
int id = 10;
_testUser = new User
{
Id = id,
// rest is your expected test data - that is what faking is about
// faked method returns simply data your test method expects
};
// Execution of method under test
MyBLMethod(id);
// Test validation
// Assert something you expect to happen on _testUser instance
// inside MyBLMethod
}
protected override IMyContext GetContext()
{
return new FakeContext();
}
protected override User GetUserFromDb(IMyContext context, int userId)
{
return _testUser.Id == userId ? _testUser : null;
}
}
As you add more methods and your application grows you will refactor those query execution methods and context factory method to separate classes to follow single responsibility on classes as well - you will get context factory and either some query provider or in some cases repository (but that repository will never return IQueryable or get Expression as parameter in any of its methods). This will also allow you following DRY principle where your context creation and most commonly used queries will be defined only once on one central place.
So at the end you can have something like this:
public class MyBLClass()
{
private IContextFactory _contextFactory;
private IUserQueryProvider _userProvider;
public MyBLClass(IContextFactory contextFactory, IUserQueryProvider userProvider)
{
_contextFactory = contextFactory;
_userProvider = userProvider;
}
public void MyBLMethod(int userId)
{
using (IMyContext entities = _contextFactory.GetContext())
{
User user = _userProvider.GetSingle(entities, userId);
// Some BL Code here
}
}
}
Where those interfaces will look like:
public interface IContextFactory
{
IMyContext GetContext();
}
public class MyContextFactory : IContextFactory
{
public IMyContext GetContext()
{
// Here belongs any logic necessary to create context
// If you for example want to cache context per HTTP request
// you can implement logic here.
return new MyDbContext();
}
}
and
public interface IUserQueryProvider
{
User GetUser(int userId);
// Any other reusable queries for user entities
// Non of queries returns IQueryable or accepts Expression as parameter
// For example: IEnumerable<User> GetActiveUsers();
}
public class MyUserQueryProvider : IUserQueryProvider
{
public User GetUser(IMyContext context, int userId)
{
return context.Users.Find(userId);
}
// Implementation of other queries
// Only inside query implementations you can use extension methods on IQueryable
}
Your test will now only use fakes for context factory and query provider.
// NUnit + Moq unit test
[TestFixture]
public class MyBLClassTest
{
private class FakeContext : IMyContext
{
// Create just empty implementation of context interface
}
[Test]
public void MyBLMethod_DoSomething()
{
// Test setup
int id = 10;
var user = new User
{
Id = id,
// rest is your expected test data - that is what faking is about
// faked method returns simply data your test method expects
};
var contextFactory = new Mock<IContextFactory>();
contextFactory.Setup(f => f.GetContext()).Returns(new FakeContext());
var queryProvider = new Mock<IUserQueryProvider>();
queryProvider.Setup(f => f.GetUser(It.IsAny<IContextFactory>(), id)).Returns(user);
// Execution of method under test
var myBLClass = new MyBLClass(contextFactory.Object, queryProvider.Object);
myBLClass.MyBLMethod(id);
// Test validation
// Assert something you expect to happen on user instance
// inside MyBLMethod
}
}
It would be little bit different in case of repository which should have reference to context passed to its constructor prior to injecting it to your business class.
Your business class can still define some queries which are never use in any other classes - those queries are most probably part of its logic. You can also use extension methods to define some reusable part of queries but you must always use those extension methods outside of your core business logic which you want to unit test (either in query execution methods or in query provider / repository). That will allow you easy faking query provider or query execution methods.
I saw your previous question and thought about writing a blog post about that topic but the core of my opinion about testing with EF is in this answer.
Edit:
Repository is different topic which doesn't relate to your original question. Specific repository is still valid pattern. We are not against repositories, we are against generic repositories because they don't provide any additional features and don't solve any problem.
The problem is that repository alone doesn't solve anything. There are three patterns which have to be used together to form proper abstraction: Repository, Unit of Work and Specifications. All three are already available in EF: DbSet / ObjectSet as repositories, DbContext / ObjectContext as Unit of works and Linq to Entities as specifications. The main problem with custom implementation of generic repositories mentioned everywhere is that they replace only repository and unit of work with custom implementation but still depend on original specifications => abstraction is incomplete and it is leaking in tests where faked repository behaves in the same way as faked set / context.
The main disadvantage of my query provider is explicit method for any query you will need to execute. In case of repository you will not have such methods you will have just few methods accepting specification (but again those specifications should be defined in DRY principle) which will build query filtering conditions, ordering etc.
public interface IUserRepository
{
User Find(int userId);
IEnumerable<User> FindAll(ISpecification spec);
}
The discussion of this topic is far beyond the scope of this question and it requires you to do some self study.
Btw. mocking and faking has different purpose - you fake a call if you need to get testing data from method in the dependency and you mock the call if you need to assert that method on dependency was called with expected arguments.
I am learning EF4.1 in conjunction with MVVM and in one of these tutorials they create a MainWindowViewModel with a Repository object that they use in calling another view model (EmployeeListViewModel). Here is the code:
public MainWindowViewModel()
{
IObjectContextAdapter adapter = ((IObjectContextAdapter)new SidekickEntities());
_vmRepository = new GenericRepository(adapter.ObjectContext);
EmployeeListViewModel viewModel = new EmployeeListViewModel(_vmRepository);
this.ViewModels.Add(viewModel);
}
public EmployeeListViewModel(GenericRepository repository)
{
if (repository == null)
{
throw new ArgumentNullException("repository");
}
_employeeRepository = repository;
this.AllEmployees = new ObservableCollection<Employee>(_employeeRepository.GetAll<Employee>());
}
What I am wondering is, why is the repository created in the MainWindowViewModel and then passed into EmployeeListViewModel? Why not just create the repository in EmployeeListViewModel like this:
public MainWindowViewModel()
{
EmployeeListViewModel viewModel = new EmployeeListViewModel();
this.ViewModels.Add(viewModel);
}
public EmployeeListViewModel()
{
IObjectContextAdapter adapter = ((IObjectContextAdapter)new SidekickEntities());
_employeeRepository = new GenericRepository(adapter.ObjectContext);
this.AllEmployees = new ObservableCollection<Employee>(_employeeRepository.GetAll<Employee>());
}
I am pretty new to EF but it seems a little cleaner to create a repository in each separate ViewModel. Wouldn't the repository then be cleaned up when the ViewModel in question is no longer used instead of keeping it around until the closing of MainWindowViewModel or does this create too many repository instances?
The problem you will run into when using a separate Context for each ViewModel is that entities that have links to each other come from different contexts so you will have to manually work this out when trying to update something (see Attaching and Detaching Objects)
This has to do with a pattern called Unit Of Work.
UoW helps you with encapsulating functions that should work together. In your case the ObjectContext implements the UoW pattern and is passed to the repository in the constructor.
You should share your ObjectContext between functions that work together and should be seen as one Unit Of Work.