Unit Testing on a Repository with Generic Parameters - asp.net-mvc

Let's say I have a Generic Repository class along the lines of the following:
public class Repository<T> : IRepository<T> where T : class
{
IObjectSet<T> source;
public Repository(IUnitOfWork transactionHandler)
{
source = transactionHandler.CreateObjectSet<T>();
}
public IQueryable<T> GetAll()
{
return source.AsQueryable<T>();
}
public void Add(T entity)
{
source.AddObject(entity);
}
//blah blah other methods
}
I am having trouble wrapping my mind around how (or even if?) I would unit test this.
Visual Studio generates a combo of tests that I can understand for the above implementation of GetAll
public void GetAllTest()
{
GetAllTestHelper<SomeExpectedType>();//expect this to pass
try
{
GetAllTestHelper<SomeUnexpectedType>();//expect this to throw exception
}
//catch exception - check it is expected type etc.
}
public void GetAllTestHelper<T>() where T : class
{
IUnitOfWork transactionHandler = IUnitOfWorkFactory.GetUnitOfWork();
Repository<T> target = new Repository<T>(transactionHandler);
IQueryable<T> actual = target.GetAll();
Assert.IsInstanceOfType(actual, typeof(IQueryable<T>));
}
The idea being - I can prove that calling this method returns an IQueryable of type T. I can also prove that it throws an InvalidOperationException for a type that an IObjectSet cannot be generated for (also required/desired).
For the Add method I am going round in circles.
For the 'why' - why have a test - I think I want to prove that I can add a type of T to the repository and then prove it has been added to the DB.
For the 'how' - using the VS default as above, I get something along the lines of
public void AddTest()
{
AddTestHelper<SomeExpectedType>();
}
public void AddTestHelper<T>() where T : class
{
IUnitOfWork transactionHandler = UnitTestHelper.GetUnitOfWork();
Repository<T> target = new Repository<T>(transactionHandler);
T entity = default(T);
target.Add(entity);//throws exception - value cannot be null
}
So my question is
a) how would you unit test this repository?
or possibly
b) would you test this repository?

a) how would you unit test this repository?
A mock framework such as Rhino Mocks or Moq could simplify the task of unit testing this class. It would be used to mock the IUnitOfWork interface that is passed to the constructor of the repository.
For example here's how a typical unit test of the Add method for this repository might look like using Rhino Mocks:
[TestMethod]
public void Add_Should_Use_AddObject_On_Underlying_Source()
{
// arrange
var uofStub = MockRepository.GenerateStub<IUnitOfWork>();
var objectSet = MockRepository.GenerateStub<IObjectSet<string>>();
uofStub.Stub(x => x.CreateObjectSet<string>()).Return(objectSet);
var sut = new Repository<string>(uofStub);
var entity = "foo bar";
// act
sut.Add(entity);
// assert
objectSet.AssertWasCalled(x => x.AddObject(entity));
}
As far as the automatic combo of tests generated by Visual Studio are concerned IMHO that's probably one of the most useless ever feature in VS.
b) would you test this repository?
Yes, absolutely.

Related

Why use database factory in asp.net mvc?

Recently I have worked with asp.net mvc and I have seen in sample project is using Database Factory class. How can you explain for me why use it ?
IDatabaseFactory class
public interface IDatabaseFactory : IDisposable
{
EFMVCDataContex Get();
}
DatabaseFactory class
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new EFMVCDataContex());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
This is an example of an Abstract Factory design pattern. The idea is to create a seam to provide loose coupling between the classes so another type of context could be swapped, either for testing purposes or to extend the application.
Generally speaking, a factory is a way to manage short-lived dependencies, such as database connections. Typically, a framework exposes a way to inject an instance of the factory and then the framework can work with it based on an interface (in this case IDatabaseFactory) as a contract between the framework, and the framework user. The framework will have code that looks something like this:
public interface ISomeService
{
void DoSomething();
}
public class SomeService()
{
private readonly IDatabaseFactory factory;
// The factory is injected through the constructor
public SomeService(IDatabaseFactory factory)
{
this.factory = factory;
}
public void DoSomething()
{
using (EFMVCDataContex context = this.factory.Get())
{
// Run a LINQ query here using the context
} // This bracket disposes the context
}
}
The service can then be instantiated for a much longer lifetime than the context that is created by the factory. What's more is that the context is always properly disposed in this scenario.
Now, the main benefit from doing this is that you can swap the DatabaseFactory with an alternate implementation (commonly referred to as the Liskov Substitution Principle):
public class MyDatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new AlternateDataContext());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
Assuming that AlternateDataContext inherits (or implements) EFMVCDataContex, MyDatabaseFactory can be swapped apples-for-apples with DatabaseFactory without making any changes to SomeService.
MyDatabaseFactory could be coded with a connection string in the constructor, giving you a way to connect to alternate databases, for example.
Of course, another great benefit of doing this is to create a mock implementation of IDatabaseFactory that can be used to test the DoSomething method. In a unit test, SomeService (the class under test) should be the only real class being used, IDatabaseFactory should be a mock (which could either be done by hand coding a class, or using a mocking framework).

NUnit - Mock Repository and test with dummy data

I'm trying to establish a way of unit testing my service layer (& repositories) using some dummy data. I've seen examples of this before with Generic Repositories but I'm struggling to get something working whilst using a DatabaseFactory.
When I call the GetPhrase method from repository.Object I just get null back everytime.
I'm using NUnit and Moq. Any pointers on where i'm going wrong would be appreciated, or let me know if i'm better off going down a different road
e.g. Connecting to a local db for tests (SQL CE etc)
Here are the main components of the code:
public class PhraseRepository : RepositoryBase<Phrase>, IPhraseRepository
{
public PhraseRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
}
public string GetPhrase(string phraseCode)
{
return this.GetMany(p => p.PhraseCode == phraseCode).First().Descript;
}
}
public interface IPhraseRepository : IRepository<Phrase>
{
string GetPhrase(string phraseCode);
}
public class CLPRiskPhraseService : ICLPRiskPhraseService
{
private readonly IPhraseRepository phraseRepository;
public string GetPhrase(string phraseCode)
{
return phraseRepository.GetPhrase(phraseCode);
}
}
[Test]
public void GetPhrase()
{
var phrases = new FakePhraseData().GetPhrases();
phraseRepository.Setup(m => m.GetMany(It.IsAny<Expression<Func<Phrase, bool>>>())).Returns(phrases);
var result = phraseRepository.Object.GetPhrase("H300");
// Assert
NUnit.Framework.Assert.IsNotNull(phraseRepository.Object);
NUnit.Framework.Assert.AreEqual("Description0", result);
}
Invoking phraseRepository.Object.GetPhrase("H300") in your test will always return null unless you set it up to return something different.
I think you're mistakenly thinking that this call to GetPhrase will invoke GetMany like the concrete PhraseRepository does, but you need to remember that it's just a mock of the interface IPhraseRepository. A method on a mocked object will always return the default value of the return type (in this case string) unless you use Setup to change the behavior of that method.

Integration test with Ninject

I am familiar with the fact, that i should not use dependency injection in unit tests, so i can unit test each layer independently.
Still, I want to create integration tests for my controllers. Therefore I need to inject my repositories into the Controllers from a unit test.
I a following a generic approach using a T4 script, that creates a test class for each controller, containing a test method for each ActionResult. This test method should simply call the method to make sure no exceptions are thrown to the surface.
Because of using this T4 script, I cannot manually feed the repositories into the controllers. I need to make use of dependency injection.
Based on my former experience, this should work, but i keep getting the error:
Unable to get default constructor for class <<UnitTest>>
My generated classes look like this at the moment:
[TestClass]
public class TestControllersHomeController
{
private EL.NET.Web.Controllers.HomeController c;
//setup
public TestControllersHomeController(Project.Controllers.HomeController c)
{
this.c = c;
}
[ClassInitialize]
public void ClassInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
kernel.Bind<TestControllersHomeController>().ToSelf();
kernel.Bind<Project.Controllers.HomeController>().ToSelf();
}
[TestMethod]
public void TestIndex()
{
var result = c.Index();
Assert.IsNotNull(result);
}
Edit:
I already found out, that the repositories can be loaded with help of the GetService() method of IKernel. But for the Membership provider, this doesn't work.
Again, I do not want to mock the provider, I want to perform an integration test so I know if my Controller methods throw any exceptions.
The unit test must have a default constructor:
[TestClass]
public class TestControllersHomeController
{
private HomeController _sut;
[TestInitialize]
public void MyTestInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
_sut = kernel.Resolve<HomeController>();
}
[TestMethod]
public void TestIndex()
{
var result = _sut.Index();
Assert.IsNotNull(result);
}
}

How to Inject properly an IDBContextFactory into a controller's inject IDomainFactory using Ninject MVC3?

Preliminaries
I'm using Ninject.MVC3 2.2.2.0 Nuget Package for injecting into my controller an implementation of a IDomain Interface that separates my Business Logic (BL) using an Factory approach.
I'm registering my Ninject Modules in the preconfigured NinjectMVC3.cs using:
private static void RegisterServices(IKernel kernel)
{
var modules = new INinjectModule[]
{
new DomainBLModule(),
new ADOModule()
};
kernel.Load(modules);
}
I'm trying to avoid the fatal curse of the diabolic Service Locator anti-pattern.
The Domain Class uses a DBContext that i'm trying to inject an interface implementation too, via an IDBContext, with the following scenario:
IDomainBLFactory:
public interface IDomainBLFactory
{
DomainBL CreateNew();
}
DomainBLFactory:
public class DomainBLFactory : IDomainBLFactory
{
public DomainBL CreateNew()
{
return new DomainBL();
}
}
In the controller's namespace:
public class DomainBLModule : NinjectModule
{
public override void Load()
{
Bind<IDomainBLFactory>().To<DomainBLFactory>().InRequestScope();
}
}
At this point i can inject the IDomainBLFactory implementation into my controller using Ninject Constructor Injection without any problem:
public class MyController : Controller
{
private readonly IDomainBLFactory DomainBLFactory;
// Default Injected Constructor
public MyController(IDomainBLFactory DomainBLFactory)
{
this.DomainBLFactory = DomainBLFactory;
}
... (use the Domain for performing tasks/commands with the Database Context)
}
Now my central problem.
In the DomainBL implementation, i will inject the dependency to a particular DBContext, in this case ADO DBContext from Entity Framework, again, using a IDBContextFactory:
IDbDataContextFactory
public interface IDbDataContextFactory
{
myADOEntities CreateNew();
}
DbDataContextFactory
public class DbDataContextFactory : IDbDataContextFactory
{
public myADOEntities CreateNew()
{
return new myADOEntities ();
}
}
ADOModule
public class ADOModule : NinjectModule
{
public override void Load()
{
Bind<IDbDataContextFactory>().To<DbDataContextFactory>().InRequestScope();
}
}
Now in the DomainBL implementation I faced the problem of injecting the necessary interface for the DBContext Object Factory:
public class DomainBL
{
private readonly IDbDataContextFactory contextFactory;
**** OPS, i tried to understand about 10+ Stackoverflow articles ***
...
}
What have I tried?
To Use the constructor Injection. But I don't know what to inject in the call for the Factory CreateNew() in the IDBContextFactory. For clear:
public class DomainBLFactory: IDomainBLFactory
{
// Here the constructor requires one argument for passing the factory impl.
public DomainBL CreateNew()
{
return new DomainBL(?????) // I need a IDBContextFactory impl to resolve.
//It's not like in the MVC Controller where injection takes place internally
//for the controller constructor. I'm outside a controller
}
}
In this Useful Post, our unique true friend Remo Gloor describes in a comment a possible solution for me, citing: "Create an interface that has a CreateSomething method that takes everything you need to create the instance and have it return the instance. Then in your configuration you implement this interface and add an IResolutionRoot to its constructor and use this instace to Get the required object."
Questions: How do I implement this in a proper way using Ninject.MVC3 and my modest Domain Class approach? How do I Resolve the IResolutionRoot without be punished for relaying in the Service Locator anti-pattern?
To Use the property injection for an IDBContexFactory. In the course of learning and reading all the contradictory points of view plus the theoretical explanations about it, I can deduce it's not a proper way of doing the injection for my DBContexFactory class code. Nevermind. It doesn't work anyway.
public class DomainBL
{
[Inject]
public IDbDataContextFactory contextFactory
{
get;
set;
}
//Doesn't works, contextFactory is null with or without parameterless constructor
.... (methods that uses contextFactory.CreateNew()....
}
Question: What am I missing? Even if this approach is wrong the property is not injecting.
Be cursed. Use a DependencyResolver and live with the stigmata. This works and I will remain in this approach until a proper solution appears for me. And this is really frustrating because the lack of knowledge in my last 10 days effort trying to understand and do things right.
public class DomainBL
{
private readonly IDbDataContextFactory contextFactory;
this.contextFactory = DependencyResolver.Current.GetService<IDbDataContextFactory>();
//So sweet, it works.. but i'm a sinner.
}
Question: Is there a big mistake in my understanding of the Factory Approach for the injection of interfaced implementations and using a Domain Driven Approach for taking apart the Business Logic? In the case I'm wrong, what stack of patterns should I implement with confidence?
I saw before a really big quantity of articles and blogs that does not ask this important question in a open a clear way.
Remo Gloor introduces the Ninject.Extensions.Factory for the Ninject 3.0.0 RC in www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction.
Question: Will this extension work coupled with Ninject.MVC3 for general porpouse?. In such case it should be my hope for the near future.
Thank you all in advance for your guidance and remember we appreciate your kind help. I think a lot of people will find this scenario useful too.
I don't really get the purpose of your factories. Normally, you have exactly one ObjectContext instance for one request. This means you don't need the factory and can simply bind myADOEntities in Request scope and inject it into your DomainBL without adding the factories:
Bind<myADOEntities>().ToSelf().InRequestScope();
Bind<DomainBL>().ToSelf().InRequestScope();
And Yes the factory and mvc extrensions work together.
Here's an implementation of a generic IFactory to solve the problem without resorting to the ServiceLocator anti-pattern.
First you define a nice generic factory interface
public interface IFactory<T>
{
T CreateNew();
}
And define the implementation which uses ninject kernel to create the objects requested
class NinjectFactory<T> : IFactory<T>
{
private IKernel Kernel;
public NinjectFactory( IKernel Kernel )
{
this.Kernel = Kernel;
}
public T CreateNew()
{
return Kernel.Get<T>();
}
}
Binding to your factory using the following
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<myADOEntities>().ToSelf();
kernel.Bind<DomainBL>().ToSelf();
kernel.Bind(typeof(IFactory<>)).To(typeof(NinjectFactory<>));
}
You can now do the following in your controller.
public class MyController : Controller
{
private readonly IFactory<DomainBL> DomainBLFactory;
public MyController( IFactory<DomainBL> DomainBLFactory )
{
this.DomainBLFactory = DomainBLFactory;
}
// ... (use the Domain for performing tasks/commands with the Database Context)
}
And in your DomainBL
public class DomainBL
{
IFactory<myADOEntities> EntitiesFactory;
public DomainBL( IFactory<myADOEntities> EntitiesFactory )
{
this.EntitiesFactory = EntitiesFactory;
}
// ... (use the Entities factory whenever you need to create a Domain Context)
}

How to use methods in ObjectContext class, if I use IObjectSet<T> for unit test?

I am using EF4 with POCO and trying to make it testable architecture.
So I create IObjectContext interface as follow :
public interface IObjectContext
{
IObjectSet<Employee> Employees { get; }
IObjectSet<Team> Teams { get; }
void Commit();
}
Then I changed type of properties to IObjectSet in my real ObjectContext class as follow :
public partial class HRManagementEntities : ObjectContext, IUnitOfWork
{
// skip some codes here...........
public IObjectSet<Employee> Employees
{
get { return _employees ?? (_employees = CreateObjectSet<Employee>("Employees"));
}
private IObjectSet<Employee> _employees;
public IObjectSet<Team> Teams
{
get { return _teams ?? (_teams = CreateObjectSet<Team>("Teams")); }
}
private IObjectSet<Team> _teams;
public void Commit()
{
SaveChanges();
}
}
In my service layer, consume EF like this :
public class Service
{
private IObjectContext ctx;
public HRService(IObjectContext ctx)
{
this.ctx = ctx;
}
public List<Team> GetAllTeams()
{
return ctx.Teams.ToList();
}
}
Here is my problem, How to call methods in ObjectContext for example, ApplyCurrentValues(), ExecuteStoreCommand(), and so on... ?
Do I need to implement those methods in the IObjectContext to use?
EDIT
As RPM's advice, I created following extension method for ApplyCurrentValues() method, another methods could be extended in same way.
public static T UpdateModel<T>(this IObjectSet<T> iObjectSet, T currentEntity) where T : class
{
ObjectSet<T> objectSet = iObjectSet as ObjectSet<T>;
if (objectSet == null || currentEntity == null)
throw new ArgumentNullException();
return objectSet.ApplyCurrentValues(currentEntity);
}
You need to create extension methods for the methods you need, and cast the IObjectSet to ObjectSet.
For instance, if you need to do .Include (eager loading), use this extension method:
public static IQueryable<TSource> Include<TSource>(this IQueryable<TSource> source, string path)
{
var objectQuery = source as ObjectQuery<TSource>;
if (objectQuery != null)
{
objectQuery.Include(path);
}
return source;
}
You could probably do the same thing for IObjectContext, but not sure why you are even mocking this out. You should not expose the OC to outside the repository, only the repository should know about the OC.
In your example, your service is calling ctx.Teams on the entities/repository.
IMO your service should be calling ctx.Find, which would be strongly-typed (via generics) to the Teams object context. (IRepository)
A common trap is to over-mock things. Don't mock everything just for the sake of it, mock the functionality which you require for unit testing.
If you want to abstract out the Object Context then use the Unit of Work pattern.

Resources