Tuesday, November 1, 2016

Building objects for your Unit Tests

When creating unit tests I prefer to use the AAA pattern (Arrange, Act and Assert).  During the Arrange part you usually end up instantiating objects to use for the test.  Depending on the complexity of the objects you are creating this can get to be a little bit of code.  Lets look at the code below:

Note the method BuildContact.  It takes a parameter of an Action<Contact> which would allow you to pass in a lambda expression to further define the properties you want to change on the Contact object for each unit test individually.  This centralizes the logic needed to create the Contact which is helpful but another benefit is what if there was a default value used by every test.  Look at this version of the BuildContact method:

Note the defaults are before the invoking of the action.  This way if a test wanted to override the default values it can.  Normally I create a separate test class for each of the methods I am writing unit tests for.  Using this method above to create the item I am using allows me to create the object with many defaults already set.It wouldn’t be unusual to have several BuildContact methods in different test classes each specific to the needs of that class (method) specifically.

Friday, October 28, 2016

Fun with Dictionaries – Replacing ugly switch and if statements

Recently I have been using a new technique to replace those ugly if statements and switch statements with a dictionary.  Lets get started with some code first:

So that Build method with all the if statements isn’t very appealing.  Lets make it better by using a switch statement instead:

That is better but I have started to prefer using a dictionary instead.  I think this code looks better:

Adding new items is one line now instead of several with the if and switch statements.

Tuesday, December 1, 2015

Singleton Azure WebJob

I have an Azure website project I have been working on.  This project required a scheduled task to run so I decided to give Azure WebJobs a try.  Creation of the job and getting it to deploy was pretty straight forward.  One of the things that is nice is for each instance your website uses the WebJob is duplicated.  For some WebJobs this can be be a really nice feature. 

The WebJob I am using does some data import and manipulation.  Having multiple instances of this WebJob running is not what I wanted.  After some searching I found that you can make your WebJob run on a single instance no matter how many instances your website is using.

To do this you will need to do the following.

  1. Add a “settings.job” file to the root of your WebJob project
  2. Modify the properties of the file and set the:
    • Build Action = Content
    • Copy to Output Directory = Copy always
  3. The contents of the “settings.job” file should contain the following json:
    { "is_singleton": true }

This should be all that is needed to get your WebJob running as a single instance when installed on many instances.

Saturday, May 16, 2015

Setting up Web API 2 with Windsor using OWIN hosted in IIS


tldr; Get the code from my Github repository here: https://github.com/devdaves/ExampleWebApi

Start a new ASP.NET Web Application

image

Select the Empty template.  Don't check any of the core references (Web Forms, MVC or Web API).

image

Once the project is ready to go, open the package manager console and run the following commands to install the necessary nuget packages.

  • install-package Microsoft.AspNet.WebApi.Owin
  • install-package Microsoft.Owin.Host.SystemWeb
  • install-package Castle.Windsor

Open the web.config and add the following code:

<appSettings>
  <add key="owin:AutomaticAppStartup" value="true" />
</appSettings>

In the Solution Explorer create a Startup class at the root of the site with the following code:

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        appBuilder.UseWebApi(config);
    }
}

In the Solution Explorer create a Models folder and inside the Models folder create a Contact class with the following code:

public class Contact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

In the Solution Explorer create a Controllers folder and inside the Controllers folder create a Web API controller called ContactsController with the following code:

public class ContactsController : ApiController
{
    [HttpGet]
    [Route("contacts")]
    public IHttpActionResult Get()
    {
        return Ok(new Contact(){FirstName = "Donald", LastName = "Duck"});
    }
}

At this point you have enough to run the application and should be able to go to http://localhost:####/contacts in your browser and see the contact returned.

Now its time to add Windsor.  In the Solution Explorer add a new folder called Windsor.  Create a new class called WindsorDependencyScope with the following code:

internal class WindsorDependencyScope : IDependencyScope
{
    private readonly IWindsorContainer _container;
    private readonly IDisposable _scope;

    public WindsorDependencyScope(IWindsorContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        _container = container;
        _scope = container.BeginScope();
    }

    public object GetService(Type t)
    {
        return _container.Kernel.HasComponent(t)
        ? _container.Resolve(t) : null;
    }

    public IEnumerable<object> GetServices(Type t)
    {
        return _container.ResolveAll(t)
        .Cast<object>().ToArray();
    }

    public void Dispose()
    {
        _scope.Dispose();
    }
}

Add a new class to the Windsor folder called WindsorHttpDependencyResolver with the following code:

internal sealed class WindsorHttpDependencyResolver : IDependencyResolver
{
    private readonly IWindsorContainer _container;

    public WindsorHttpDependencyResolver(IWindsorContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        _container = container;
    }

    public object GetService(Type t)
    {
        return _container.Kernel.HasComponent(t)
            ? _container.Resolve(t) : null;
    }

    public IEnumerable<object> GetServices(Type t)
    {
        return _container.ResolveAll(t)
        .Cast<object>().ToArray();
    }

    public IDependencyScope BeginScope()
    {
        return new WindsorDependencyScope(_container);
    }

    public void Dispose()
    {
    }
}

In the Windsor folder create a new folder called Installers.  Create a new class in the Installers folder called ControllerInstaller with the following code:

public class ControllerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
        .Pick().If(t => t.Name.EndsWith("Controller"))
        .Configure(configurer => configurer.Named(configurer.Implementation.Name))
        .LifestylePerWebRequest());
    }
}

Create another new class in the Windsor/Installers folder called DefaultInstaller with the following code:

public class DefaultInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .Pick()
            .WithServiceDefaultInterfaces()
            .Configure(c => c.LifestyleTransient()));
    }
}

Now we need to make the final changes to the Startup class we created in the root of the site.  Make it look like this:

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        var container = new WindsorContainer().Install(
            new ControllerInstaller(),
            new DefaultInstaller());
        var httpDependencyResolver = new WindsorHttpDependencyResolver(container);

        HttpConfiguration config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.DependencyResolver = httpDependencyResolver;
        appBuilder.UseWebApi(config);
    }
}

Now that Windsor is setup lets add a contact repository and add that as a dependency to the controller so we can see Windsor in action.

In the Solution Explorer add a folder called Repository.  In the Repository folder add a new interface called IContactsRepository with the following code:

public interface IContactsRepository
{
    Contact GetContact();
}

Add a class called ContactsRepository to the Repository folder with the following code:

public class ContactsRepository : IContactsRepository
{
    public Contact GetContact()
    {
        return new Contact(){FirstName = "Donald", LastName = "Duck"};
    }
}

Now lets go add the dependency to the ContactsController, make the ContactsController code look like this:

public class ContactsController : ApiController
{
    private IContactsRepository repository;

    public ContactsController(IContactsRepository repository)
    {
        this.repository = repository;
    }

    [HttpGet]
    [Route("contacts")]
    public IHttpActionResult Get()
    {
        return Ok(this.repository.GetContact());
    }
}

That should be it.  Running the site now everything should work.

Monday, May 5, 2014

Pimp your Bash console on Windows

Since I have been doing so much Git work I wanted to post some things I do to pimp my Bash console out.

First thing is we need to get to our home directory.  Do this by typing this in your bash console:

cd

This should change your prompt to point to ~.  The next thing is we need to see if there is already a .bashrc file.  The easiest way I have found to do this is to type the following in the bash console:

explorer .

This should open a windows explorer window in your home directory.  Check to see if a .bashrc file exists.  If this file does not exist type the following in the bash console window:

touch .bashrc

Go back to windows explorer and you should now see the .bsahrc file.  Open the file in your favorite text editor.  Here is an example of what I have been putting in my .basrc file:

alias brc="source ~/.bashrc"
alias cls=clear
alias ..='cd ..'
alias cd..='cd ..'
alias dir='ls --color -X'
alias e='explorer .'

h()
{
    cd ~/skydrive/dev;
}

cl() {
    d=$1
    if [[ -z "$d" ]]; then
        d=$HOME
    fi
    if [[ -d "$d" ]]; then
        cd "$d"
        dir
    else
        echo "bash: cl: '$d': Directory not found"
    fi
}



brc an easy way to reload the bashrc file while in the bash console.  This way you don’t have to restart the console each time you make a change.
cls I am used to typing this in DOS
.. a shortcut to go back a directory
cd.. bash wants a space between the cd and the .. this alias lets me forget the space and it doesn’t complain about it.
dir I am used to typing this in DOS
e shortcut to open explorer in the current directory
h shortcut to my start directory where all my code is
cl change directory and list its contents

Saturday, March 29, 2014

Git Config Commands

I have been doing a bunch of work with Git lately.  I wanted to do a post about some commands I don’t want to forget.

Who are you?
git config --global user.name '<name goes here>'
git config --global user.email '<email address here>’

Turn off https verification
We are using Stash and its using a self signed certificate.  This command allows us to access the Stash repositories over HTTPS.

git config --global http.sslVerify false

Make notepadd++ your editor (no more vim)
I am not a VIM kinda guy so this was a huge help when using things like rebase.

git config --global core.editor '"C:/Program Files (x86)/Notepad++/notepad++.exe" -multiInst -nosession –noPlugin'

Set Visual Studio 2013 as your diff tool
git config --global difftool.prompt true
git config --global difftool.vs2013.cmd '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vsdiffmerge.exe" "$LOCAL" "$REMOTE" //t'
git config --global difftool.vs2013.keepbackup false
git config --global difftool.vs2013.trustexistcode true
git config --global diff.tool vs2013

Set Visual Studio 2013 as your merge tool
git config --global mergetool.prompt true
git config --global mergetool.vs2013.cmd '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vsdiffmerge.exe" "$REMOTE" "$LOCAL" "$BASE" "$MERGED" //m'
git config --global mergetool.vs2013.keepbackup false
git config --global mergetool.vs2013.trustexistcode true
git config --global merge.tool vs2013

Log Alias
This alias I find really useful. I got this from one of my co-workers.  Here is a link to where it came form (source).

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

Saturday, February 22, 2014

Unit Testing Async Methods with Moq

The other day I was pairing with a colleague.  We where working on unit testing some classes that where using the new async and await features.  We ran into some issue trying to get mocking working for our classes dependencies. Here is some example code on how we got things to work.

So given the following code:

public interface IClass2
{
    Task<string> GetSomeString_MethodAsync();
}

public class Class2 : IClass2
{
    public async Task<string> GetSomeString_MethodAsync()
    {
        await Task.Run(() => Thread.Sleep(2000));
        return "hello world.";
    }
}

public class Class1
{
    private IClass2 class2;

    public Class1(IClass2 class2)
    {
        this.class2 = class2;
    }

    public async Task<string> SomeMethod()
    {
        return await this.class2.GetSomeString_MethodAsync();
    }
}

And we can test it like this:

private Mock<IClass2> class2Mock;
private Class1 class1;

[TestInitialize]
public void Setup()
{
    this.class2Mock = new Mock<IClass2>();
    this.class1 = new Class1(this.class2Mock.Object);
}
            
[TestMethod]
public async Task SomeMethodTest()
{
    var expectedString = "Hello World";
    var tcs = new TaskCompletionSource<string>();
    tcs.SetResult(expectedString);
    this.class2Mock.Setup(x => x.GetSomeString_MethodAsync()).Returns(tcs.Task);

    var result = await this.class1.SomeMethod();

    Assert.AreEqual(result, expectedString);
}

Note the usage of the TaskCompletionSource in the unit test along with the declaration of the test using “async Task”.