Unit testing method in service layer - asp.net-mvc

I have started thinking about adding some unit tests around some business logic in my project.
The first method that I would like to test is a method in my service layer that returns a list of child nodes for a given node.
The method looks like this:
public List<Guid> GetSubGroupNodes(string rootNode)
{
List<Tree> tree = ssdsContext.Trees.ToList();
Tree root = ssdsContext.Trees.Where(x => x.UserId == new Guid(rootNode)).FirstOrDefault();
return GetChildNodeIds(root, tree);
}
private List<Tree> GetChildNodes(Tree rootNode, List<Tree> tree)
{
kids.Add(rootNode);
foreach (Tree t in FindChilden(rootNode, tree))
{
GetChildNodes(t, tree);
}
return kids;
}
The way I'd imaginge testing something like this is to provide a fake Tree structure and then test that a providing a node returns the correct subnodes.
ssdsContext is an ObjectContext.
I've seen that its possible to extract and interface for the ObjectContext How to mock ObjectContext or ObjectQuery<T> in Entity Framework? but I've also read that mocking a DBContext is a waste of time Unit Testing DbContext.
I have also read that as Entity Framework is an implementation of the repository pattern and unit of work patten here: Generic Repository With EF 4.1 what is the point.
This has all left me a bit confused...is the only real way to test a method like this to create a Repository Layer? Is it even worth unit testing this method?

Wrap the ObjectContext class in a wrapperclass -- let's call it ContextWrapper for fun -- that only exposes what you need from it. Then you can inject an interface of this (IContextWrapper) in to your class with your method. A wrapper can be mocked with no hooks attached to the outside world. The treestructure, as you say, is easy to create, and get from your mock object. Thus making your test TRUE unittests instead of a kind of integration test.

Related

What particular use is the interface for repository pattern?

I fully understand the idea of the design of Repository pattern. But why do we need to implement the iDepository interface class? What particular use is this for?
The repository class itself works without the interface class.
I think someone is going to answer me it's for decoupling from the business logic and the data logic.
But even if there is no interface class, isn't the data logic decoupled data logic?
It is so that you can inject a test double of the IRepository class when you are unit testing the business layer. This has the following benefits:
It allows you to easily pinpoint failing tests as being caused by the business layer rather than the repository layer;
It makes your business logic layer tests fast, as they depend neither on data access, which tends to be slow, nor set-up of a database structure and test data, which tends to be very slow.
One way to inject the test doubles when unit testing is by Constructor Injection. Suppose your Repository has the following methods:
void Add(Noun noun);
int NumberOfNouns();
And this is the code of your business class:
public class BusinessClass {
private IRepository _repository;
public BusinessClass(IRepository repository) {
_repository = repository;
}
// optionally, you can make your default constructor create an instance
// of your default repository
public BusinessClass() {
_repository = new Repository();
}
// method which will be tested
public AddNoun(string noun) {
_repository.Add(new Noun(noun));
}
}
To test AddNoun without needing a real Repository, you need to set up a test double. Usually you would do this by using a mocking framework such as Moq, but I'll write a mock class from scratch just to illustrate the concept.
public IRepository MockRepository : IRepository {
private List<Noun> nouns = new List<Noun>();
public void Add(Noun noun) {
nouns.Add(noun);
}
public int NumberOfNouns() {
return nouns.Count();
}
}
Now one of your tests could be this.
[Test]
public void AddingNounShouldIncreaseNounCountByOne() {
// Arrange
var mockRepository = new MockRepository();
var businessClassToTest = new BusinessClass(mockRepository);
// Act
businessClassToTest.Add("cat");
// Assert
Assert.AreEqual(1, mockRepository.NumberOfNouns(), "Number of nouns in repository should have increased after calling AddNoun");
}
What this has achieved is that you have now tested the functionality of your BusinessClass.AddNoun method without needing to touch the database. This means that even if there's a problem with your Repository layer (a problem with a connection string, say) you have assurance that your Business layer is working as expected. This covers point 1 above.
As for point 2 above, whenever you're writing tests which test the database you should make sure it's in a known state before each test. This usually involves deleting all the data at the beginning of every test and re-adding test data. If this isn't done then you can't run assertions against, say, the number of rows in a table, because you won't be sure what that's supposed to be.
Deleting and re-adding test data would normally be done by running SQL scripts, which are slow and vulnerable to breakage whenever the database structure changes. Therefore it's advisable to restrict the use of the database only to the tests of the repository itself, and use mocked out repositories when unit testing other aspects of the application.
As for the use of abstract classes - yes, this would provide the same ability to supply test doubles. I'm not sure which code you would choose to put in the abstract base and which the concrete implementation, though. This answer to an SO question has an interesting discussion on abstract classes vs interaces.
First, you must understand what the Repository pattern is. It's an abstraction layer so that rest of the application do not have to care where the data comes from.
Abstractions in .NET is typically represented by interfaces as no logic (code) can be attached to an interface.
As a bonus that interface also makes it easier for you to test your application since you can mock the interface easily (or create a stub)
The interface also allows you to evolve your data layer. You might for instance start by using a database for all repository classes. But later you want to move some logic behind a web service. Then you only have to replace the DB repository with a WCF repository. You might also discover that an repository is slow and want to implement a simply memory cache within it (by using memcache or something else)
I found a very useful msdn page demonstrating the idea of Repository and Test Driven Development
.
http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspx

Overriding IOC Registration for use with Integration Testing

so I think I'm perhaps not fully understanding how you would use an IOC container for doing Integration tests.
Let's assume I have a couple of classes:
public class EmailComposer : IComposer
{
public EmailComposer(IEmailFormatter formatter)
{
...
}
...
public string Write(string message)
{
...
return _formatter.Format(message);
}
}
OK so for use during the real application (I'm using autofac here) I'd create a module and do something like:
protected override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<HtmlEmailFormatter>().As<IEmailFormatter>();
}
Makes perfect sense and works great.
When it comes to Unit Tests I wouldn't use the IOC container at all and would just mock out the formatter when I'm doing my tests. Again works great.
OK now when it comes to my integration tests...
Ideally I'd be running the full stack during integration tests obviously, but let's pretend the HtmlEmailFormatter is some slow external WebService so I decide it's in my best interest to use a Test Double instead.
But... I don't want to use the Test Double on all of my integration tests, just a subset (a set of smoke-test style tests that are quick to run).
At this point I want to inject a mock version of the webservice, so that I can validate the correct methods were still called on it.
So, the real question is:
If I have a class with a constructor that takes in multiple parameters, how do I make one of the parameters resolve to a an instance of an object (i.e. the correctly setup Mock) but the rest get populated by autofac?
I would say you use the SetUp and TearDown (NUnit) or ClassInitialize and ClassCleanup (MSTest) for this. In initialize you register your temporary test class and in cleanup you restore to normal state.
Having the DI container specify all the dependencies for you has the benefit of getting an entire object graph of dependencies resolved. However if there's a single test in which you want to use a different implementation I would use a Mocking framework instead.

Can you mock/stub an internal property?

//class = Person
public string Name { get; internal set; }
I have an object with several different fields that are declared as shown above. I would like to use Moq so I can unit test the repository. The repository simply returns a list of names, so I would like to setup Moq to work with it like so:
var personRepositoryMock = new Mock<IPersonRepository>();
personRepositoryMock
.Setup(p => p.GetNames())
.Returns(new List<Person>
{
new Person{Name = "Hulk Hogan"}
});
Being new to mocking and unit testing in general, I have a couple of questions:
What are my options to stub out the Person class in my scenario?
What is the benefit of mocking in this situation? I read and read and read, but I can't seem to get my head around why I see examples like this, testing a repository. Mocks make sense to me when I have to unit test business logic, but not so much in the data layer. Any words of wisdom to clear this up for me?
Thanks.
1) You can use the "InternalsVisibleTo" attribute on the assembly (in AssemblyInfo.cs) that contains the repository class, to give the Moq assembly access to it.
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("YourTestClass")]
2) Mocking decouples your data layer from being a dependency requirement for unit tests.
Think of it this way: you won't be creating a Mock to test the repository itself. You're creating the mock for other classes to use as a fake data source, to test their functionality that requires input data from the repository in the real application.
If you can accurately predict the data cases that your repository will provide, then you can mock those cases as fake input, and not require that your unit tests actually connect to the database to get live data to use.
Your example won't actually unit test anything in the repository (other than the parameterless constructor!) so ... I don't know where you're seeing these examples, but I don't feel that the code above is providing anything useful "as is".

How to unit test with persistence ignorance

I'm working on a new project where I'm actively trying to honor persistence ignorance. As an example, in my service layer I retrieve an entity from my ORM and I call a routine defined on the entity that may or may not make changes to the entity. Then I rely on my ORM to detect whether or not the entity was modified and it makes the necessary inserts/updates/deletes.
When I run the application it works as intended and it's really neat to see this in action. My business logic is very isolated and my service layer is really thin.
Of course, now I'm adding unit tests and I have noticed that i can no longer write unit tests that verify whether or not certain properties were modified. In my previous solution, I determine whether or not a repository call was made with the object in its expected state.
mockRepository.Verify(mr =>
mr.SaveOrUpdate(It.Is<MyEntity>(x =>
x.Id == 123 && x.MyProp == "newvalue")), Times.Once());
Am I approaching persistence ignorance correctly? Is there a better way to unit test the post-operational state of my entities when I don't explicitly call the repository's save method?
If it helps, I'm using ASP.NET MVC 3, WCF, NHibernate, and NUnit/Moq. My unit tests make calls to my controller actions passing instances of my service classes (which are instantiated with mocked repositories).
You are approaching this correctly in that you have an interface representing your repository and passing in a fake in your tests, I prefer to use an in-memory simulator for my repositories instead of using mocks because I find that stub implementations tend to make my tests less brittle than using mock/verify (as per the mocks aren't stubs article linked above). If your repository has Add/Find/Delete methods, my in-memory implementation will forward those to a member list and then save will set a property called SavedList that I can assert on in my tests.
Oddly enough I just stumbled upon a solution and it is really simple.
[Test]
public void Verify_Widget_Description_Is_Updated()
{
// arrange
var widget = new Widget { };
mockWidgetRepo.Setup(mr => mr.GetWidget()).returns(widget);
var viewModel = new WidgetVM { };
viewModel.Description = "New Desc";
// act
var result = (ViewResult)controller.UpdateWidget(viewModel);
// assert
Assert.AreEqual("New Desc", widget.Description);
}
It's not perfect, but I can assume that if widget.Description matches the value I assigned to my view model, then the ORM would save that change unless evict was called.
UPDATE:
Just came up with another alternative solution. I created a ObjectStateAssertionForTests(Object obj) function in my base repository that does nothing. I can call this function in my code and then check it in my unit tests.
mockRepository.Verify(mr =>
mr.ObjectStateAssertionForTests(It.Is<MyEntity>(x =>
x.Id == 123 && x.MyProp == "newvalue")), Times.Once());

Access to Entity Manager in ASP .NET MVC

Greetings,
Trying to sort through the best way to provide access to my Entity Manager while keeping the context open through the request to permit late loading. I am seeing a lot of examples like the following:
public class SomeController
{
MyEntities entities = new MyEntities();
}
The problem I see with this setup is that if you have a layer of business classes that you want to make calls into, you end up having to pass the manager as a parameter to these methods, like so:
public static GetEntity(MyEntities entityManager, int id)
{
return entityManager.Series.FirstOrDefault(s => s.SeriesId == id);
}
Obviously I am looking for a good, thread safe way, to provide the entityManager to the method without passing it. The way also needs to be unit testable, my previous attempts with putting it in Session did not work for unit tests.
I am actually looking for the recommended way of dealing with the Entity Framework in ASP .NET MVC for an enterprise level application.
Thanks in advance
Entity Framework v1.0 excels in Windows Forms applications where you can use the object context for as long as you like. In asp.net and mvc in particular it's a bit harder. My solution to this was to make the repositories or entity managers more like services that MVC could communicate with. I created a sort of generic all purpose base repository I could use whenever I felt like it and just stopped bothering too much about doing it right. I would try to avoid leaving the object context open for even a ms longer than is absolutely needed in a web application.
Have a look at EF4. I started using EF in production environment when that was in beta 0.75 or something similar and had no real issues with it except for it being "hard work" sometimes.
You might want to look at the Repository pattern (here's a write up of Repository with Linq to SQL).
The basic idea would be that instead of creating a static class, you instantiate a version of the Repository. You can pass in your EntityManager as a parameter to the class in the constructor -- or better yet, a factory that can create your EntityManager for the class so that it can do unit of work instantiation of the manager.
For MVC I use a base controller class. In this class you could create your entity manager factory and make it a property of the class so deriving classes have access to it. Allow it to be injected from a constructor but created with the proper default if the instance passed in is null. Whenever a controller method needs to create a repository, it can use this instance to pass into the Repository so that it can create the manager required.
In this way, you get rid of the static methods and allow mock instances to be used in your unit tests. By passing in a factory -- which ought to create instances that implement interfaces, btw -- you decouple your repository from the actual manager class.
Don't lazy load entities in the view. Don't make business layer calls in the view. Load all the entities the view will need up front in the controller, compute all the sums and averages the view will need up front in the controller, etc. After all, that's what the controller is for.

Resources