Tidycode

Tidy and clean code

Conditions added to Fluent Tests

leave a comment »

When writing unit tests for a controller, you need to cast the result to the appropriate class, normally to a ViewResult.

            var customerController = new CustomerController();
           
var
result = customerController.Details(3);

            Ensure.That(result).Is.Not.Null();
           
Ensure.That(result).Is.InstanceOfType<ViewResult
>();
           
var viewResult = result as ViewResult
;
           
Ensure.That(viewResult.Model).Is.InstanceOfType<Customer
>();
           
var customer = viewResult.Model as Customer
;
           
Ensure.That(customer.FirstName).Is.EqualTo("Charlie");

With the new conditions in Fluent Tests you’ll cast the object automatically when asserting.

            var customerController = new CustomerController();
           
var
result = customerController.Details(3);

            Ensure.That(result).Is.InstanceOfType<ViewResult>()
                    .And(a => a.Model).Is.InstanceOfType<
Customer
>()
                    .And(a => a.FirstName).Is.EqualTo(
"Charlie");

This way you get to write the unit test clear and without all the noise you get when declaring variables and doing casts.

Written by arvander

June 20, 2011 at 9:26 pm

Posted in Uncategorized

Unit Testing, Dependency Injection and ASP.NET MVC

leave a comment »

So, yet another article about this subject? Well, not quite, I want to discuss another way to solve this that has a different approach. First, lets look at the classic way to solve the Controller/Repository pattern. Second, we’ll take a look at a different approach using something called a SessionContext. One basic idea about MVC is to be able to perform good unit tests. And to do this we would normally use dependency injections and foremost, constructor injection. The standard pattern is that the controllers has a constructor that takes a repository as a parameter, or rather the interface of a repository.

    public class MyController : Controller
    {
       
private readonly IMyRepository
repository;

        public MyController(IMyRepository repository)
        {
           
this
.repository = repository;
        }

        public ActionResult Index()
        {
           
var
items = repository.GetItems();
           
return View(items);
        }
    }

 

As you can see, the constructor of the controller takes the interface IMyRepository as a parameter. This makes it possible to mock the repository as in the example below.

[TestFixture]
   
public class MyControllTest
    {
        [
Test
]
       
public void
TestIndex()
        {
           
var mock = new Mock<IMyRepository
>();
            mock.Setup(a => a.GetItems()).Returns(
new List<string>() 
                                                      {
                                                      
"Item1", "Item2"
´
                                                      });
           
var
repository = mock.Object;
           
var controller = new MyController
(repository);
           
var viewResult = controller.Index() as ViewResult
;
           
Ensure
.That(viewResult).Is.Not.Null();
           
Ensure.That(viewResult.Model).Is.InstanceOfType<List<string
>>();
           
Ensure.ThatEnumerable((List<string>)viewResult.Model).Has.Elements();
        }
    }

When this controller is used in a real situation we define a new ControllerFactory within the Global.asax.   

 
    public class ControllerFactory : DefaultControllerFactory
    {
       
public override IController CreateController(
                                 RequestContext requestContext, string
controllerName)
        {
           
// resolve the controller with your choice of DI-container
            return base.CreateController(requestContext, controllerName);
        }
    }
 

So far so good. But what about a controller that serves several methods and these methods needs different type of repositories. That will make you end up with a controller with a long parameter list in the constructor. Again, nothing actually wrong about that but it seems like somewhat unnecessary.

Introducing SessionContext

The class SessionContext encapsulates every request and automatically discovers the current user. The SessionContext holds a reference to a session and the session is coupled to the user in the current scope. The SessionContext can be instanciated at any time and is also nestable and when nesting a SessionContext a new session will only be created if new credentials are used.

using (var ctx = new SessionContext())

   
using (var innerCtx = new SessionContext
()) 
    {
        
var
outerSession = innerCtx.Session;
        
var
innerSession = innerCtx.Session;
        
Assert
.AreSame(outerSession, innerSession);
        
using (var mostInnerCtx = new SessionContext(new WebIdentity
()))
         {
            
var
mostInnerSession = innerCtx.Session;
            
Assert.AreNotSame(mostInnerSession, innerSession);
         } 
    } 
}

So, what does this really mean? Well, the SessionContext also handles resolving objects using a dependency injection container. Currently, SessionContext is using Ninject for this but could be using StructureMap or any other as well. The fact that we can resolve objects from a session that is available at any time makes it easy to handle the dependency issue between a Controller and a repository.

public class MyOtherController : Controller

   
public ActionResult
Index() 
    { 
       
using (var ctx = new SessionContext
()) 
        { 
           
var repository = ctx.Resolve<IMyRepository
>(); 
           
var
items = repository.GetItems(); 
           
return View(items); 
        } 
    } 
}

This leaves us with a cleaner controller with no constructor and the repository is resolved only when needed. It also makes it easy to use new repositories without the need for refactoring the controller. The obvious downside is that it is hiding the dependencies. Using this solution you can’t really see which repositories that are needed by the controller as you would if they were supplied by the constructor.

User awareness in SessionContext

Any more upsides? Yes, for instance, this way we always knows who are executing the code and this makes it easier to verify permissions etc. The idea is to use attributes to perform authorization against the domain but that will be discussed in a later blog. Always having access to the user is also convenient when logging, adding create and modified by info to the database etc. Now you think that I’m a bit lost. The user is available from the current HttpContext right? Well, that’s true but what if you run the code in a framework that isn’t MVC? It might be code in a layer common for desktop apps as well as a web app. For this reason SessionContext will detect the user regardless of the platform, if you create a SessionContext in a desktop environment, the identity will be that of the windows user. On the web it will be the user currently logged in or an anonymous user. There might arise situations where you would like to elevate the permissions when making a function call, much like the “Run as administrator” in windows. Creating a new SessionContext with the administration user credentials will solve this.

 

Ensuring SessionContext for all requests

As we resolved the controller when using dependency injection constructors with a ControllerFactory, we will do the same for SessionContext. The difference is that we will be using Castle to create a proxy. The proxy will make sure that all methods executed for a Controller will be wrapped in a SessionContext.

public class SessionContextControllerFactory : DefaultControllerFactory
    {
       
private readonly ProxyGenerator proxyGenerator = new ProxyGenerator
();
       
public override IController CreateController(
                         
RequestContext requestContext, string
controllerName)
        {
           
IController originalController = base
.CreateController(
                                                requestContext, controllerName);
           
return proxyGenerator.CreateInterfaceProxyWithTarget(
                               originalController,
new ControllerInterceptor
());
        }
    }

    public class ControllerInterceptor : IInterceptor
    {
       
public void Intercept(IInvocation
invocation)
        {
           
using (var ctx = new SessionContext
())
            {
               
// Add manual injections to the context here if needed
                invocation.Proceed();
            }
        }

    }

The repositories are registered to Ninject in the Application_Start of Global.asax by an injection module.

Unit testing with SessionContext

One big question is left, how do we perform unit tests with SessionContext? When using the “normal” pattern for controllers and repositories we mocked the repository and fed it to the controller. We will do the same when using SessionContext except that we will inject the mock into the session.

    [TestFixture]
   
public class ControllerTestUsingSessionContext
    {
        [
Test
]
       
public void
TestIndex()
        {
           
using (var ctx = new SessionContext
())
            {
               
var mock = new Mock<IMyRepository
>();
                mock.Setup(a => a.GetItems()).Returns(
new List<string>()
                                                         {
"Item1", "Item2"
});
               
var
repository = mock.Object;
                ctx.Session.Inject(repository);

                var controller = new MyOtherController();
               
var viewResult = controller.Index() as ViewResult
;
               
Ensure
.That(viewResult).Is.Not.Null();
               
Ensure.That(viewResult.Model).Is.InstanceOfType<List<string
>>();
               
Ensure.ThatEnumerable((List<string>)viewResult.Model).Has.Elements();
            }
        }

Unit testing with different credentials

Again, the user of the SessionContext, since we always know who is executing the code we can easily perform different unit tests to check different credentials.

        [Test]
       
public void
TestIndexWhenAdministrator()
        {
           
var
identity = GetUserThatIsAdministrator();
           
using (var ctx = new SessionContext(identity))
            {
                TestIndex();
            }
        }

Since the SessionContext’s could be nested we can easily create a new SessionContext with a specific user and then call the same unit test, this time with a specific user. That’s it for now, I will write more about this and hopefully add some code to Codeplex soon.

Written by arvander

May 4, 2011 at 10:05 pm

Generics and Fluent Tests

leave a comment »

The recent changes in Fluent Tests was to introduce the usage of lambda expressions. With lambdas, we can add constraints when asserting collections.

 

However, a problem with generics arises. The Ensure class has two methods that is colliding

        public static EnsuredWrapper<T> That<T>(T compareValue)
        {
           
return new EnsuredWrapper
<T>(assertionProvider, compareValue);
        }

        public static CollectionEnsuredWrapper<IEnumerable<TElementType>, 
                              TElementType> That<TElementType>           
                              (
IEnumerable
<TElementType> enumerable)
                              where TElementType : class
                              {            
                                 return new
CollectionEnsuredWrapper<IEnumerable<TElementType>,
                                                            TElementType>(assertionProvider, enumerable);
        }

These two methods, both called That, will compete and the latter will loose. That is because the generic expression in the first method is to greedy. Since there is no way to add a generic constraint that states that a generic parameter shouldn’t be of a specific type, there is no other way than to rename the method.

Another solution, and this is made in MSTest (the CollectionAssert class) , is to create a new Ensure class, CollectionEnsure that defines a correct That-method. So, which solution is prefered ?

Ensure.ThatEnumerable(list).Where(a=>a.EndsWith(“*”)).Has.ElementCount(5);

CollectionEnsure.That(list).Where(a=>a.EndsWith(“*”)).Has.ElementCount(5);

The current implementation is using the first option with the ThatEnumerable-method.

Written by arvander

May 4, 2011 at 9:20 am

Posted in Uncategorized

Language support added to Fluent Tests

leave a comment »

Language support has been added upon a request. By simply delegating new language specific methods to the existing extension methods, a new language was created.

That means that we now can write test fluently in either english or swedish.

English : Ensure.That(5).Is.GreaterThan(4)

Swedish : Försäkra.Att(5).Är.StörreÄn(4)

Good or bad? I wont decide but I’ll stick with the english version myself. One problem that arises though are what Are is translated into? Any swedish user that has a suggestion, please leave a comment!

Written by arvander

May 3, 2011 at 11:25 pm

Posted in Uncategorized

Writing custom assertion handlers for Fluent Tests

leave a comment »

With Fluent Tests you can write tests in your own domain language using custom assertions handlers.

As an example, say you have a class Company and this class has a reference to another class Address, seems like a not so very uncommon scenario. In your unit tests you might want to assert that the company has an address. In a normal scenario this would be done like this :

Assert.IsTrue(company.Address!=null)

Well it’s readable, you can se that an assert is made and the address of the company should be set to an instance of a object. If this is done on several occasions you might want to consider using Fluent Tests.

With Fluent Tests you write a custom assertion handler that really just is an extension method. The extension method will be applied to a verb within the Fluent Tests framework.

First off, lets define so classes from the domain, Company and Address.

 

    public class Company
    {
       
public string Name { get; set; }
       
public Address Address { get; set
; }
    }

    public class Address
    {
       
public string StreetName { get; set; }
       
public string PostalCode { get; set
; }
       
public string ZipCode { get; set
; }
    }

The actual assertion handler is written as an extension method for the verb Has. In this case we won’t compare the value against another value so the only parameter in our extension method will be the verb.

    public static class CustomAssertionHandler
    {
       
public static void Address(this Has<Company
> verb)
        {
           
VerbAssert<Company>.Assert(verb,c=>c.Address==null,
                                           "Company has no address");
        }
    }

In our extension method we are using a helper class from the framework, VerbAssert. This class makes it easy to write the actual implementation by using a lambda expression as the actual assert method. When the lambda expression c=>c.Address==null is true, an assertion should be made. If an assertion should be made, an AssertionException will be thrown with the message “Company has no address”.

Now we can use our new assertion handler by simply typing Ensure.That(company).Has.Address();. You are now writing tests in your own domain language!

    [TestFixture]
   
public class CustomAssertionHandlerTest
    {
        [
Test
]
       
public void
TestCompanyForAddress()
        {
           
var company = new Company
();
           
Ensure.That(company).Has.Address();
        }
    }

Written by arvander

May 3, 2011 at 5:42 pm

More functions added to Fluent Tests

leave a comment »

Fluent Tests is continually being extended with more functionality. The basic types of tests are now available and more are coming soon.

Written by arvander

May 2, 2011 at 11:09 pm

Posted in Uncategorized

FluentTests now on CodePlex

leave a comment »

As of today, the 29th of april 2011, the FluentTests project is now available on CodePlex (fluenttests.codeplex.com).

Written by arvander

April 29, 2011 at 10:22 pm

Posted in Uncategorized