Being Cellfish

Stuff I wished I've found in some blog (and sometimes did)

May, 2013

Change of Address
This blog has moved to blog.cellfish.se.
Posts
  • Being Cellfish

    How would I test a WebAPI controller

    • 1 Comments

    Kind of related to my previous post, this article on how to test ASP.Net WebAPI controllers made me think. As you can see from the article it is fairly easy to get your controller under test, but it does take some work to get everything setup properly. And I have never tested my WebAPI controllers like that.

    First of all my experience is that since WebAPI provides an MVC model it is very tempting to write your application logic as controllers. I mean, that is what MVC is all about. However almost all MVC and MVVM frameworks I've been exposed to end up with some dependency that is very specific to the target application (ex: HttpResponseMessage in WebApi). I like my application logic to be 100% isolated from presentation which means that the controller of WebAPI is not the place for my application logic. The only thing the WebAPI controller should do in my opinion is to translate between HTTP and my application logic.

    This creates a situation where I can test my application logic easily and if necessary reuse it in different types of applications (WebAPI vs Console apps vs WinForm apps). The WebAPI layer then becomes so thin that I can feel confident that it works even without any unit tests. That is how I would do it... However if I have some extra time to spend on writing unit tests, adding a test or two that verifies the conversion between HTTP and my application logic is not so bad either and the article mentioned above is a good help. But that would be icing on the cake.

  • Being Cellfish

    If it is hard to test, you did something wrong

    • 2 Comments

    I've often been asked questions like how would you test this or been told that there cannot be unit test for some code because it is impossible to test. Well, my opinion is that if something is hard to test it is all your fault. You designed it, you implemented it and hence it is your fault it is hard to test.

    The situation in which people have the hardest time accepting that it is their own fault is when dealing with external dependencies. They say things like "I'm using this other module that does not provide a nice interface". And then they typically revert to some mocking framework to cleanup their mess. Most mocking frameworks today are powerful enough through reflection or even binary instrumentation that they magically can make untestable code very untestable.

    Rather than using powerful tools as my savior, I use abstractions. Whenever I depend on something that is not easy to test and that I do not have the power to change I hide it behind an abstraction; an interface or just a class with a few virtual methods I can override in my tests. Is this abstraction just another level of indirection? I do not believe so. Isolating dependencies makes it possible for me to implement something the way I want it to be and then deal with the behavior of the dependency separately. Here is an example from real life:

    I needed to implement a feature that depended on two components that really didn't lend them selves for easy faking. So I created two new interfaces representing the functionality I needed for my feature. As I started to integrate the first component it became clear that the interface I needed was not provided by the dependency in an easy way. I needed to put some logic in there to make it work the way my feature expected it. So I created a new interface representing the dependency functionality and made that a dependency of a class that added the logic needed to transform dependency results into what my feature needed. I did not expect this but it was easy given my design and the fact I did not know exactly how the dependency worked in the beginning did not stop me from being productive. My second dependency turned out to behave the way I expected and the interface I invented could easy be used to wrap the second dependency.

    The key is that the wrapper for each external dependency should be thin. Preferably one-liners so there is no need to test them. That does not mean the method signature needs to be the same as your dependency. I often make my wrapper signature simpler than what the dependency actually needs.

    And remember; if it is hard to test - You did something wrong!

  • Being Cellfish

    Collection initializers not doing what you expect

    • 1 Comments

    Let's assume that you have a class that have a collection property and that you want the default for that collection to be to actually have a value. That class might look like this:

     1: class Foo
     2: {
     3:     public Foo()
     4:     {
     5:         this.Numbers = new List<int> { 4711 };
     6:     }
     7:     public ICollection<int> Numbers { get; set; }
     8: }
    

    Now somewhere else in your code you want to override the collection value and set some other value so you do this:

     9: var foo= new Foo { Numbers = { 42 } };
    

    So what is now the value of the property Numbers? Turns out it actually holds both the initial value and the new value rather than just the one value you want. The way to do it if you only want one value is this:

     9: var foo= new Foo { Numbers = new List<int> { 42 } };
    

    One way to try and avoid this is to not initialize the Numbers property with a list but rather an array like this:

     5:         this.Numbers = new[] { 4711 };
    

    But that might not always be possible so you might be better off by not exposing your collections like this and only provide an IEnumerable property for enumeration and do all manipulation through separate methods and not properties.

  • Being Cellfish

    Task-based Asynchronous Pattern - kick starter

    • 0 Comments

    Regardless of if you are new to TAP (Task-based Asynchronous Pattern aka "async/await") or have been doing it for a while this presentation from an MVP summit in February (2013) serves both as a good introduction explaining how it works as well as providing deeper knowledge and high-lighting a few common problems. It's a short presentation so definitely worth downloading and reading!

Page 1 of 1 (4 items)