Achieving unit testability of Presenter while using CSLA Framework with WCSF - unit-testing

The WCSF uses Model View Presenter (MVP) pattern for organizing/structuring the source code for a website. When MVP pattern is used correctly, it provides seperation of concerns, unit testability of presenter logic, etc.
How to make WCSF and CSLA framework play well (work together) for achieving unit testability of the presenter logic. For achieving the unit testability of the presenter logic it is required that all data access and other dependencies needs to be mocked or stubbed out.

When executing the data portal methods within a CSLA object, the content of those data portal methods should call dataservices to get and update that data. Those web services should just be interface based so that they can be mocked out.
Here is an example of populating an employee object:
private void DataPortal_Fetch(SingleCriteria<Employee, int> criteria)
{
IEmployeeDTO data = DataServiceContext.Current.EmployeeDataService.GetEmployee(criteria.Value);
// Just do left to right copying here
LoadProperty<int>(IdProperty, data.Id);
}
Then EmployeeDataService is just an interface. We use Ninject to create a concreate class for that interface that will point to another assembly for the data access technology you want to use. You can then specify a different concrete class for the test class.
Here is the example data service interface:
public interface IEmployeeDataService
{
IEmployeeDTO GetEmployee(int id);
}
Here is the example data service concreate class for using Linq 2 SQL:
namespace XXX.DataServices.Linq
{
public class EmployeeDataService : IEmployeeDataService
{
public IEmployeeDTO GetEmployee(int id)
{
// use Linq to SQL to get the data and transform that class into IEmployeeDTO
}
}
}
Here is the example data service to use for testing:
namespace XXX.DataServices.Testing
{
public class IEmployeeDTO GetEmployee(int id)
{
// mock up several IEmployeeDTO objects with known data
}
}

Related

How to unit test a class that consumes a web service?

I have a class (lets call it A) that:
In the constructor takes a config and based on it, creates a stub of
a web service and stores a reference to it in a private field.
Has a few methods that call web methods and some stuff inbetween.
I started to create a unit test that:
Creates an instance of a class A with a dummy configuration.
Through reflection it injects the mocked web service stub.
Although that web service has plenty of methods.
Should I mock them all (in every test, with different data)?
Or maybe I should create another layer that encapsulates only the web methods that are being used?
Or there is another approach?
You should create a wrapper interface around your webservice, and make your class under test take a dependency on that interface, rather than directly on the webservice; you can then mock the interface. Only make that interface expose the methods of the webservice that you find interesting. This is known as a facade pattern, and is detailed here.
Without having a clue about what you're testing, aim for something like this:
public interface IWebserviceWrapper
{
Whatever DoStuff(int something);
}
public class WebserviceWrapper : IWebserviceWrapper
{
private WebService _theActualWebservice;
public WebserviceWrapper(Webservice theService)
{
_theActualWebService = theService;
}
public Whatever DoStuff(int something)
{
return _theActualWebservice.DoSomething(something);
}
}
Then your test would look like this (in this case, using MOQ)
public void Test_doing_something()
{
Mock<IWebserviceWrapper> _serviceWrapperMock = new Mock<IWebserviceWrapper>();
_serviceWrapperMock.SetUp(m => m.DoStuff(12345)).Returns(new Whatever());
var classUnderTest = new ClassUnderTest(_serviceWrapperMock.Object);
var result = classUnderTest.Dothings(12345);
Assert.Whatever....
}
Short answer Yes :). Long answer you should use some kind of mocking lib for example: http://code.google.com/p/mockito/ and in your unit test mock the WS stub and pass it to the tested class. That is the way of the force :)
When you unit test a class, you always want to make sure to only test that class and not include its dependencies. To do that, you will have to mock your WS to have it return dummy data when methods are called. Depending on your scenarios, you do not have to mock ALL the methods for each test, I would say only those that are used.
For an example about mocking, you can read this article: http://written-in-codes.blogspot.ca/2011/11/unit-tests-part-deux.html

How to mock with LLBLGen

How can you mock LLBLGen? I see that there is an ILinqMetaData interface but it doesn't provide any useful methods to mock out. I'm assuming you would want to program to the ILinqMetaData interface as well as the generated entity interfaces to keep objects loosely coupled to the data. Does anyone have any examples of simple tests/mocks?
I think it's not limited to LLBLGen, maybe this can help:
What's the best strategy for unit-testing database-driven applications?
Personally, I don't normally test my database access or repositories, just the logic that operates on the entities, or integration tests that operate on the entire stack (including the DB).
UPDATE: does this help? it allows you test your logic by mocking the IOrderRepository without having to do any fetch/persistence logic:
public class MyBusinessLogic
{
IOrderRepository orders;
public MyBusinessLogic(IOrderRepository orders)
{
this.orders = orders;
}
public DoSomethingTestable(OrderEntity order)
{
order.Total = 100;
orders.Save(order);
}
}

Entitity Framework 4.1 - Code First- Unit testing data access layer

I'm a .NET developer and I'm writing tests for my data access layer. I have tests that use fake repository - I have achieved that by using Moq and Ninject.
I'm getting my head around EntityFramework 4.1 Code First model and I'd like to create a prototype for CRUD routines. It's an MVC app, so my entities won't be tracked by a context.
To me it feels wrong that I'm writing tests that will make changes to the database. I will then have to clear the database each time I want to run these tests. Is this the only way to test CRUD routines?
Thank you
How do you expect to test data access if you don't access the data? Yes data access should be tested against real database. There is very simple workaround for your problem. Make your test transactional and rollback changes at the end of the test. You can use base class like this (NUnit):
[TestFixture]
public abstract class BaseTransactionalTest
{
private TransactionalScope _scope = null;
[SetUp]
public void Initialize()
{
_scope = new TransactionalScope(...);
}
[TearDown]
public void CleanUp()
{
if (_scope != null)
{
_scope.Dispose();
_scope = null;
}
}
}

Should unit tests know about NHibernate?

I'm following on from a previous question. The answer I accepted involves using a generic IRepository to handle basic CRUD, wrapped with a domain specific IMovieRepository which delegates to the generic setup. A further detail involves having a WrapQueryInSession method on the generic IRepository:
IEnumerable<T> WrapQueryInSession(Func<ISession, IEnumerable<T>> query);
I was getting to implementation when I realized that this exposes the NHibernate ISession to consumers of the generic repository. NHibernate is otherwise fully contained in the IRepository implementation, but for that method signature.
This comes to the fore when I want to unit test MovieRepository, by having an IRepository, implemented in RepositoryFake, passed to the MovieRepository constructor:
protected override void BeforeEachTest()
{
_fixture = new MovieRepository(new RepositoryFake());
}
My test class has a private fake repository implementation:
private class RepositoryFake : IRepository<Movie>
{
...
public IEnumerable<Movie> WrapQueryInSession(Func<ISession, IEnumerable<Movie>> query)
{
...
}
...
}
The way this is set up, the test class, and any other consumer of an IRepository implementation, is made aware of the ISession from NHibernate, and thus NHibernate itself. This seems a case of a leaky abstraction.
Is there a better way to fully contain use of NHibernate within an IRepository implementation?
The idea from my answer to your previous question was that the generic IRepository is only known inside your infrastructure layer - it is not published outside of this. When you publish the ISession to the non-generic repositories they gain a very versatile interface, as they have access to the ISession for querying. The problem with not exposing the ISession is that your generic repository will either:
Limit your querying capabilities or
Have a whole host of different methods for querying (basically duplicating the interface of the ISession.
Seems a bit of a waste having NHibernate's querying interface hidden away inside a facade (which the generic Repository would be limited to).
IMO, if you choose nHibernate, you should leverage the power it gives you and live with the dependence through-out your infrastructure dll (including tests). Think of the generic IRepository interface as a helper interface to NHibernate to reduce the amount of duplicate code inside the repositories.
I agree with the principle that NHibernate should not be abstracted completely but I have found that the querying interface of NHibernate can be hidden away without too much hassle and that can happen by using Query objects.
Each query object should leverage the power the NHibernate provides (ISession, ICriteria, IQuery, etc) and can be executed by the implementation of the IRepository.
Having Query objects instead of methods in your repositories offers better testability and it would not require any references to NHibernate in your test classes.
Here is how the whole thing could look like:
public interface IRepository
{
ISession Session { get; }
TResult Query<TResult>(IQuery<TResult> query);
}
public class Repository : IRepository
{
public ISession Session
{
get { return /* Call the session factory to return an ISession */; }
}
public TResult Query<TResult>(IQuery<TResult> query)
{
return query.Execute(Session));
}
}
public interface IQuery<TResult>
{
TResult Execute(QueryContext context);
}
public abstract class Query<TResult> : IQuery<TResult>
{
public abstract TResult Execute(ISession session);
}
public class GetPeopleByName: IQuery<Person>
{
private readonly string _name;
public GetPeopleByName(string name)
{
_name = name;
}
public override IList<Person> Execute(ISeesion session)
{
var query = context.Session.CreateCriteria(typeof(Person))
.Add(Restrictions.Eq("Name", _name));
return query.List<Person>();
}
}
Then you can use the above like:
IRepository repository = /* Get somehow the implementation */
IList<Person> people = repository.Execute(new GetPeopleByName("Anna"));

How to mock ObjectContext or ObjectQuery<T> in Entity Framework?

How to mock ObjectContext or ObjectQuery in Entity Framework?
The basic mocking frameworks can only create mocks for interfaces and for abstract classes (but only for abstract/virtual methods).
As the ObjectContext is neither abstract nor interface, it is not so easy to mock it. However, as the concrete model container is generated as partial class (if you use the designer), you can extract the methods/properties you need from it to an interface. In your code, you may use the interface only, that you can mock afterwards.
With the ObjectQuery it is a little bit more easy, as it has a base interface (e.g. IQueryable) that basically contains all the neccessary operations that you usually need (and required for LINQ). So you should expose IQueryable instead of ObjectQuery in your business logic, and you can create mock for that interface.
Other alternative is to hide all data-access related logic into a separate layer (with minimal logic), test this layer with integration tests, and mock it to be able to unit test the other layers.
There are tools (I know only TypeMock) that use the profiling hooks of .NET to generate the mocks. These tools are not limited to mock interfaces or abstract classes, but with them you can mock basically anything, including non-virtual and static methods. With such a tool you don't need to change your business logic in order to allow mocking.
Although this approach is sometimes useful, you have to be aware that extracting the dependencies to interfaces (IoC) is not only helpful for mocking, but also it reduces the dependencies between your components, that has other benefits too.
Personally I like Rhino.Mocks the best from the freeware tools, but we also use TypeMock as well, which is also a great product (but you have to pay for it).
Why can't we just create the actual context object to be used in our tests? Since we don't want our tests to affect the production database, we can always specify a connection string that points to a test database. Before running each test, construct a new context, add the data you will need in your test, proceed with the unit test, then in the test cleanup section, delete all the records that were created during the test. The only side-affect here would be that the auto-increment IDs would be used up in the test database, but since it's a test database - who cares?
I know that most answers regarding this question propose using DI/IoC designs to create interfaces for data contexts etc. but the reason I am using Entity Framework is exactly to not write any interfaces for my database connections, object models, and simple CRUD transactions. To write mock interfaces for my data objects and to write complex queryable objects to support LINQ, defeats the purpose of relying on highly-tested and reliable Entity Framework.
This pattern for unit testing is not new - Ruby on Rails has been using it for a long time and it's worked out great. Just as .NET provides EF, RoR provides ActiveRecord objects and each unit test creates the objects it needs, proceeds with the tests, and then deletes all the constructed records.
How to specify connection string for test environment? Since all tests are in their own dedicated test project, adding a new App.Config file with a connection string for the test database would suffice.
Just think of how much headache and pain this will save you.
I agree with the others you cannot really Mock ObjectContext. You should use EF DbContext because you can mock the underlying DbSet There are quite a lot of post how to do that. So I won't write how to do it. However if you absolutely must use ObjectContext (for some reason) and you want to Unit test it you can use InMemory database.
First install this Nuget package: Effort (Entity Framework Fake ObjectContext Realization Tool), which uses NMemory as the database. Install Effort.EF6 package:
PM> Install-Package Effort.EF6
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using Effort;
public class DbContextHelper
{
//Fake object you can drop this if you are using your own EF context
private class DbObject
{
public Guid Id { get; set; }
public string Name { get; set; }
}
//Fake EF context you can switch with you own EF context
private class FakeDbContext : DbContext
{
public FakeDbContext(DbConnection connection)
: base(connection, true) { }
public virtual DbSet<DbObject> DbObjects { get; set; }
}
private FakeDbContext _dbContext;
public DbContextHelper()
{
//In memory DB connection
DbConnection effortConnection = DbConnectionFactory.CreatePersistent("TestInstanceName");
_dbContext = new FakeDbContext(effortConnection);
}
//You can expose your context instead of the DbContext base type
public DbContext DbContext => _dbContext;
public ObjectContext ObjectContext => ((IObjectContextAdapter)_dbContext).ObjectContext;
//Method to add Fake object to the fake EF context
public void AddEntityWithState(string value, EntityState entityState)
{
DbContext.Entry(new DbObject() { Id = Guid.NewGuid(), Name = value }).State = entityState;
}
}
Usage:
DbContextHelper _dbContextHelper = new DbContextHelper();
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Added);
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Modified);
var objs = _dbContextHelper.ObjectContext.GetObjectStateEntries(EntityState.Modified | EntityState.Added);
There you are you have your object in memory DB.