How to implement FIND method of EF in Unit Test? - c#

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.

Related

How to configure dependency injection container with Func<T, Result>?

BusinessAction is used to represent an action that can be performed by a user. Each action is related to the specific entity, so if for example, that entity is Order, business actions could be CancelOrder, IssueRefund, etc.
public abstract class BusinessAction<T>
{
public Guid Id { get; init; }
public Func<T, bool> IsEnabledFor { get; init; }
}
public class CancelOrderAction : BusinessAction<Order>
{
public CancelOrderAction ()
{
Id = Guid.Parse("0e07d05c-6298-4c56-87d7-d2ca339fee1e");
IsEnabledFor = o => o.Status == OrderStatus.Active;
}
}
Then I need to group all actions related to the specific type.
public interface IActionRegistry
{
Task<IEnumerable<Guid>> GetEnabledActionIdsForAsync(Guid entityId);
}
public class ActionRegistry<T> : IActionRegistry
where T : BaseEntity
{
private readonly IEnumerable<BusinessAction<T>> _actions;
private readonly IRepository<T> _repository;
public ActionRegistry(IEnumerable<BusinessAction<T>> actions, IRepository<T> repository)
{
_actions = actions;
_repository = repository;
}
public async Task<IEnumerable<Guid>> GetEnabledActionIdsForAsync(Guid entityId)
{
var entity = await _repository.FindByIdAsync(entityId);
return entity == null
? Enumerable.Empty<Guid>()
: _actions.Where(a => a.IsEnabledFor(entity)).Select(a => a.Id);
}
}
Finally, there is an API endpoint that receives entity type (some enumeration that is later on mapped to real .NET type) and ID of an entity. The API endpoint is responsible to return action IDs that are enabled for the current state of the entity.
public class RequestHandler : IRequestHandler<Request, IEnumerable<Guid>>>
{
private readonly Func<Type, IActionRegistry> _registryFactory;
public RequestHandler(Func<Type, IActionRegistry> registryFactory)
{
_registryFactory = registryFactory;
}
public async Task<IEnumerable<Guid>> Handle(Request request, CancellationToken cancellationToken)
{
var type = request.EntityType.GetDotnetType();
var actionRegistry = _registryFactory(type);
var enabledActions = await actionRegistry.GetEnabledActionIdsForAsync(request.EntityId);
return enabledActions;
}
}
The question is: How can I configure the dependency injection container in ASP.NET (using default option or Autofac) so that Func<Type, IActionRegistry> can be resolved?
For parameters in ActionRegistry<T> I guess I can do:
builder.RegisterAssemblyTypes().AsClosedTypesOf(typeof(BusinessAction<>));
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
But, how can I configure Func<Type, IActionRegistry> so that I am able to automatically connect a request for Order with ActionRegistry<Order>? Is there a way to do that or I will need to manually configure the factory by writing some switch statement based on type (and how will that look)?
Is there a better way to achieve what I need here? The end goal is that once I have runtime type, I can get a list of business actions related to that type as well as a repository (so that I can fetch entity from DB).
What you're trying to do is possible, but it's not a common thing and isn't something magic you'll get out of the box. You'll have to write code to implement it.
Before I get to that... from a future perspective, you might get help faster and more eyes on your question if your repro is far more minimal. The whole BusinessAction<T> isn't really needed; the RequestHandler isn't needed... honestly, all you need to repro what you're doing is:
public interface IActionRegistry
{
}
public class ActionRegistry<T> : IActionRegistry
{
}
If the other stuff is relevant to the question, definitely include it... but in this case, it's not, so adding it in here just makes the question harder to read through and answer. I know I, personally, will sometimes just skip questions where there's a lot of extra stuff because there are only so many hours in the day, you know?
Anyway, here's how you'd do it, in working example form:
var builder = new ContainerBuilder();
// Register the action registry generic but not AS the interface.
// You can't register an open generic as a non-generic interface.
builder.RegisterGeneric(typeof(ActionRegistry<>));
// Manually build the factory method. Going from reflection
// System.Type to a generic ActionRegistry<Type> is not common and
// not directly supported.
builder.Register((context, parameters) => {
// Capture the lifetime scope or you'll get an exception about
// the resolve operation already being over.
var scope = context.Resolve<ILifetimeScope>();
// Here's the factory method. You can add whatever additional
// enhancements you need, like better error handling.
return (Type type) => {
var closedGeneric = typeof(ActionRegistry<>).MakeGenericType(type);
return scope.Resolve(closedGeneric) as IActionRegistry;
};
});
var container = builder.Build();
// Now you can resolve it and use it.
var factory = container.Resolve<Func<Type, IActionRegistry>>();
var instance = factory(typeof(DivideByZeroException));
Assert.Equal("ActionRegistry`1", instance.GetType().Name);
Assert.Equal("DivideByZeroException", instance.GetType().GenericTypeArguments[0].Name);

How do you avoid passing a DI container in a unidirectional api design?

I have a business layer with business entities designed using Active Record, and a unidirectional api surface. I have two distinct problems:
Without complicating the code, how should runtime values be handled, such as passing in an id value from the DAL to a constructed object? Would this be done with parameter overrides?
How do create other business entities and pass dependencies if I am not passing the container down as well (making it more of an anti-pattern / service locator)
Product is the root that wraps the container and acts as our application facade, and entry point to the rest of the BAL. The piece I am trying to solve is in Product.FindCustomer and Customer.FindDocument
public class Product
{
private IUnityContainer container;
public void RegisterType<T>() ...
public void RegisterType<TFrom, TTo>() ...
public Customer FindCustomer(string customerNumber)
{
var id = context.Customers
.Where(p => p.CustomerNumber == customerNumber)
.Select(p => p.Id)
.Single();
var customer = container.Resolve<Customer>(...); // param override?
customer.Load();
return customer;
}
}
public class Customer : BusinessEntity<Data.Customer, Guid>
{
private readonly IDocumentFileProvider provider;
public Customer(IDataContext context, IDocumentFileProvider provider) : base(context)
{
this.provider = provider;
}
public Customer(IDataContext context, IDocumentFileProvider provider, Guid id) : base(context, id)
{
this.provider = provider;
}
public Document FindDocument(string code)
{
var id = context.Documents
.Where(p => p.CustomerNumber == customerNumber)
.Select(p => p.Id)
.Single()
var document = new Document(context, provider, id); // Here is the issue
document.Load();
return document;
}
}
public class Document : BusinessEntity<Data.Document, Guid>
{
public Document(IDataContext context, IDocumentFileProvider provider) : base(context)
{
this.provider = provider;
}
public Document(IDataContext context, IDocumentFileProvider provider, Guid id) : base(context, id)
{
this.provider = provider;
}
public IDocumentFile GetFile()
{
return provider.GetFile();
}
}
Here is briefly the other classes.
public abstract class ActiveRecord<TEntity, TKey>
{
protected ActiveRecord(IDataContext context)
{
}
public virtual void Load() ...
public virtual void Save() ...
public virtual void Delete() ...
}
public abstract class BusinessEntity<TEntity, TKey> : ActiveRecord<TEntity, TKey>
{
protected BusinessEntity(IDataContext context) : base(context)
{
}
protected BusinessEntity(IDataContext context, TKey id) : this(context)
{
}
...
}
The hierarchies can be quite deep, but a shorter example:
var customer = product.FindCustomer("123");
var account = customer.FindAccount("321");
var document = account.FindDocument("some_code");
var file = document.GetFile();
One of my goals is to A) model the domain, and B) provide a very easy to understand API. Currently our BAL uses Service Locator, but I am experimenting on replacing that with proper IoC/DI and a container.
The deeper the API, and the more dependencies are needed, all the higher up class constructors can be quite long, and may no longer seem cohesive.
While DI can be squeezed into most application designs using half-measures, the unfortunate truth is that not all application designs are particularly DI friendly. Creating "smart entities" seems like magic when it comes to API design, but the fact of the matter is that at their core they violate the SRP (load and save are separate responsibilities regardless of how you slice it).
You basically have 4 options:
Find a design that is more conducive of DI and use its object model for your API
Find a design that is more conducive of DI and create a facade object model for your API
Use property injection to load your dependencies and give the end user control over the constructor
Use a service locator
I ran into a similar wall when trying to use CSLA in conjunction with DI and after many attempts, finally decided that it was CSLA that needed to go and to find a better design approach.
For a time, I tried using option 3. In this case you can create a facade wrapper around the DI container, and only expose its BuildUp() method through a static accessor. This prevents the use of the container as a service locator.
[Dependency]
public ISomeDependency SomeDepenency { get; set; }
public Customer()
{
Ioc.BuildUp(this);
}
Some DI containers can inject properties using fluent configuration instead of attributes (so your business model doesn't need to reference the container), but this can make the DI configuration very complex. Another option is to make build your own attributes.
Options 1 and 2 would be similar. You basically make every responsibility into its own class and separate your "entities" out into dumb data containers. An approach that works well for this is to use Command Query Segregation.
public class FindCustomer : IDataQuery<Customer>
{
public string CustomerNumber { get; set; }
}
public class FindCustomerHandler : IQueryHandler<FindCustomer, Customer>
{
private readonly DbContext context;
public FindCustomerHandler(DbContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public Customer Handle(GetCustomer query)
{
return (from customer in context.Customers
where customer.CustomerNumber == query.CustomerNumber
select new Customer
{
Id = customer.Id,
Name = customer.Name,
Addresses = customer.Addresses.Select(a =>
new Address
{
Id = a.Id,
Line1 = a.Line1,
Line2 = a.Line2,
Line3 = a.Line3
})
.OrderBy(x => x.Id)
}).FirstOrDefault();
}
}
Using option 1, the end user would create an instance of FindCustomer and call queryProcessor.Handle(findCustomer) (the queryProcessor is injected).
Using option 2, you would then need to create a wrapper API. You could use a fluent builder approach (more info here) to provide logical default dependencies, but allow the end user to call methods to supply their own.
var customer = new CustomerBuilder().Build(); // defaults
var customer = new CustomerBuilder(c =>
c.WithSomeDependency(new SomeDependency()).Build(); // overridden dependency
Unfortunately, the main issue with this is that control of the lifetime of objects is no longer up to the DI container, so dependencies like DbContext need special handling.
Another variant of this would be to make each entity into a humble object that internally builds up its own DI container using the other (loosely coupled) API objects. This is the recommended approach for legacy frameworks (such as web forms) that are difficult to use with DI.
Finally, there is making a static service locator that all of your API objects use to resolve their dependencies. While this best accomplishes the goal, it is something that should be considered a last resort. The biggest issue is that you lose the ability to quickly and easily understand what dependencies a class requires. So, you are either forced to create (and update) documentation indicating what the dependencies are to the end user, or end users will have to go digging through the source code to find out. Whether using a service locator is acceptable depends on your target audience and how frequent you expect them to need to be able to customize dependencies beyond the defaults. If custom dependencies are a once in a blue moon thing, it may work, but if 25% of your user base needs to add custom dependencies, service locator is probably not the right approach.
The bottom line is that if maintainability is your main goal, then option 1 is the clear winner. But if you are married to this particular API design, you will need to choose one of the other options and live with the extra maintenance involved in supporting such an API.
References:
DI Friendly Library
Dependency Injection in .NET.

EF6 DbSet<T> returns null in Moq

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);

Dependency Injection - where to put my repository object

I am currently in the process of converting a large web service to use the repository pattern and dependency injection. We are expanding our team and the benefits of reliable unit testing outweighs the effort required to refactor the code.
I have chosen Ninject as my framework based on the recommendation of a colleague and have begun refactoring my code. This has involved creating a "Common" project that contains the objects themselves, a Repository.Database project to contain the data access logic, and a web service that uses both. I have used convention based mapping so that IPersonRepository should map to my concrete PersonRepository class.
I am currently taking the approach of creating a "Repository" property on each class with the [Inject] attribute, then replacing my constructors to use said repository, but have run into my first stumbling block and am not convinced I am doing things the right way. Before I started all this, I would instantiate an object like so:
var p = new Person(ID);
And using the format I suggested, my class looks something like this:
[Inject]
public IPersonRepository Repository { get; set; }
public string Name;
public Person(int ID)
{
// This feels wrong
var p = Repository.Get(ID);
Name = p.Name;
}
You can probably see my conundrum. How can I use a constructor without having to return a new object from the repository and then map each field to my current object? I can't replace "this", and while I could use something like AutoMapper to map each field in one go, it feels like I am doing something inherently wrong here.
I could use a static method instead of an injector:
[Inject]
public static IPersonRepository Repository { get; set; }
public string Name;
public static Person GetByID(int ID)
{
return Repository.Get(ID);
}
But as you can see it requires making Repository static, and it feels like I should be using a constructor rather than a static "GetByID" method. That could just be because I am so used to using a constructor.
Alternatively I can pass the Repository into the Person constructor, but again, it feels messy to do that every time I instantiate a Person in code.
What I am trying to achieve is to have my existing WCF project load all of its data using one repository, and for my Unit Test project to load all its data using another. I don't want to have to pass concrete implementations of IPersonRepository in either. Is this achievable and even recommended?
Your entities should not need to know anything about where or how they are stored. The idea of the repository pattern is to take the responsibility of persistence away from the business logic. Practically this means you would set up your service as follows:
Create separate repositories for each "top level" entity
Inject the repositories into your web service/controller/business object
Define your entities as regular business objects with state and behavior
have the web service etc use the repository to fetch the entities as needed via ID
You should't need to call a constructor with an ID from the business logic...that's a bad pattern
You would still use the constructor to instantiate a new entity that you would then submit to the repository e.g. personRepository.Add(new Person("Bob"))
This would then have the added benefit of making your web service testable by injecting a mocked repository and not having to worry about how the entities would get retrieved in your code itself.
I've created a small helper class : "EntityResolver" which implements the "IValueResolver" interface which was introduced recently in AutoMapper. This helper class can retrieve an entity from the repository when an Id is supplied.
1) AutoMapper configuration to map a ViewModel to an Entity is defined as follows:
Mapper.CreateMap<EmployeeVM, Employee>()
.ForMember(e => e.EmployeeNumber, opt => opt.MapFrom(vm => vm.Number))
// Other propeties omitted
.ForMember(e => e.Company, opt => opt.ResolveUsing<EntityResolver<Company>>().FromMember(vm => vm.CompanyId))
;
2) Code for the EntityResolver
public class EntityResolver<TEntity> : IValueResolver where TEntity : class, IEntity, new()
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New(ResolveObject(source));
}
private object ResolveObject(ResolutionResult source)
{
if (!source.Context.Options.Items.ContainsKey("Services")) return null;
var services = (List<object>)source.Context.Options.Items["Services"];
var item = services.FirstOrDefault(s => s is IBaseService<TEntity>);
if (item == null) return null;
var id = (long)source.Value;
if (id <= 0) return null;
var service = (IBaseService<TEntity>)item;
return service.GetById(id);
}
}
3) When mapping the ViewModel to an Entity, I supply additional IMappingOperationOptions
Mapper.Map<TEntity>(viewModel, opt => opt.Items["Services"] = GetServices());
4) The GetServices method just returns all services needed to resolve the entities used in the Employee object.
protected override List<object> GetServices()
{
var services = base.GetServices();
services.Add(_companyService);
services.Add(_functionService);
services.Add(_subfunctionService);
services.Add(_countryService);
return services;
}
For more details see my test project.

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