Refactoring tips and tricks: Exceptions

Consider the following class:

    public class FooService
    {
        private readonly ILogger _logger;

        public FooService(ILogger logger)
        {
            _logger = logger;
        }

        public void Foo()
        {
            try
            {
                // Foo code goes here...
            }
            catch (Exception ex)
            {
                _logger.LogException(ex);
            }
        }

        public void Bar()
        {
            try
            {
                // Bar code goes here...
            }
            catch (Exception ex)
            {
                _logger.LogException(ex);
            }
        }
    }
    

This is a very common scenario that I’ve seen in many different places over the last few years – each method has some code wrapped in a try-catch block. To get rid of the code duplication is easy, we can move the try-catch block to a new method that will take a delegate as a parameter (code to be executed):

    private void Try(Action action)
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            _logger.LogException(ex);
        }
    }

Refactoring the class:

    public class FooService
    {
        private readonly ILogger _logger;

        public FooService2(ILogger logger)
        {
            _logger = logger;
        }

        public void Foo()
        {
            Try(() => {
                // Foo code goes here...
            });
        }

        public void Bar()
        {
            Try(() => {
                // Bar code goes here...
            });
        }

        private void Try(Action action)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                _logger.LogException(ex);
            }
        }
    }

 

 

Advertisements

Using Resharper to detect localizable strings

A few months I had to estimate how much time/effort was involved in localizing one .NET application. As part of this task I had to search for all the hard-coded strings in the source code that should be localizable, which is a tedious and very time-consuming task.

The good thing is that Resharper has good localization support which can save you many hours or even days of work – imagine having to go through all files and search for the strings manually! In this post I’ll show you how you can use Resharper to detect localizable strings and how you can enable or disable localization for a particular project, class, method or even an individual string.

Continue reading

Running tests in Bamboo after a deployment

I’ve been using Bamboo CI Server for the last few months to automate builds and deployments. I like the tool because it has good integration with Jira (both tools are from Atlassian), it’s easy enough to configure new builds and deployments, triggers, notifications, etc.

But I realised that something important was missing: Bamboo allows you to add a test runner task in a build project but not in a deployment project! This means that you can’t run tests after a successful deployment (smoke tests, integration tests, …), at least not without a workaround.

The trick is to configure your test runner as an executable in Bamboo. These are the steps in order to configure NUnit and run tests in a deployment project (it should work for any other test runner):

 

1. Add a new executable for NUnit

Go to Bamboo Administration and click on “Executables” on the left panel.

01 bamboo administration

Click on “add an executable as a server capability

02 click link

Add the path to NUnit Console and a label for the new executable. It is important to set the type to “Command” in order to use it in a Deployment project:

03 add-executable

Click on the “Add” button to save the new command.

 

2. Add a new deployment task to run the tests

You can either add a new task for the tests to an existing deployment or add a new deployment project that will only run the tests.

I decided to add a new deployment project that will be triggered after a successful deployment because it’s easier to understand if there is actually a problem with the deployment itself or if the integration tests are failing. Also, this way I am able to run the tests at any time without having to deploy the application.

Whatever your choice is, add a new “Command” task to the deployment project:

04 - add-new-task

In the “Executable” dropdown you should be able to find the command you configured for NUnit. Add arguments and environment variables if necessary:

06 - configure-nunit-task

Save the task and run the deployment. This is an excerpt of the generated log that contains the test results:


NUnit-Console version 2.6.4.14350
Copyright (C) 2002-2012 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment - 
   OS Version: Microsoft Windows NT 6.2.9200.0
  CLR Version: 2.0.50727.8009 ( Net 3.5 )

ProcessModel: Default    DomainUsage: Default
Execution Runtime: net-4.0
..F.F.F.F
Tests run: 5, Errors: 0, Failures: 4, Inconclusive: 0, Time: 6.8491962 seconds
  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0

Errors and Failures:
1) Test Failure : GivenAnUrl_WhenGettingPage_ShouldreturnSuccessStatusCode("/Home.aspx")
     Expected: True
  But was:  False

2) Test Failure : GivenAnUrl_WhenGettingPage_ShouldreturnSuccessStatusCode("/Services/Activate.aspx")
     Expected: True
  But was:  False

3) Test Failure : GivenAnUrl_WhenGettingPage_ShouldreturnSuccessStatusCode("/Administration/LostPassword.aspx")
     Expected: True
  But was:  False

4) Test Failure : GivenAnUrl_WhenGettingPage_ShouldreturnSuccessStatusCode("/Shop/Product/List.aspx")
     Expected: True
  But was:  False

Failing task since return code of [C:\Program Files (x86)\NUnit 2.6.4\bin\nunit-console.exe integration-tests-uat.nunit --config="release"] was 4 while expected 0
Finished task 'Run integration tests' with result: Failed
Finalising the build...
Stopping timer.
Build 12484609-16973828-16613398 completed.
Finished processing deployment result Deployment of 'release-16' on 'UAT - Integration Tests'

That’s it! The output is not nicely formatted as in the build tasks but it does the job – you can see how many tests were run and how many have failed (if any).

Using Dictionaries to replace long if or switch statements

Imagine the following scenario – you have created some validators for your models: Foo, Bar and Xyz.

    public interface IValidator
    {
        bool Validate(object model);
    }

    // Validator for Foo class
    public class FooValidator : IValidator
    {
        public bool Validate(object model)
        {
            // ...
        }
    }

    // Validator for Bar class
    public class BarValidator : IValidator
    {
        public bool Validate(object model)
        {
            // ...
        }
    }

    // Validator for Xyz class
    public class XyzValidator : IValidator
    {
        public bool Validate(object model)
        {
            // ...
        }
    }

You decide to create a factory class for the validators to prevent users from creating instances directly using the new keyword. For example, this code would create a validator for Foo:

    var model = new Foo();
    var validatorFactory = new ValidatorFactory();
    IValidator validator = validatorFactory.CreateValidatorFor<Foo>();

    if (validator.Validate(model))
    {
        // ...
    }

Implementation of the factory:

    using System;

    public class ValidatorFactory
    {
        public IValidator CreateValidatorFor<T>()
        {
            Type modelType = typeof (T);
            IValidator validator = CreateValidatorFor(modelType);

            return validator;
        }

        public IValidator CreateValidatorFor(Type modelType)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }

            if(modelType == typeof(Foo))
            {
                return new FooValidator();
            }
            else if(modelType == typeof(Bar))
            {
                return new BarValidator();
            }
            else if(modelType == typeof(Xyz))
            {
                return new XyzValidator();
            }

            string errorMessage = string.Concat("Could not find validator for type ", modelType.FullName);
            throw new ArgumentException("modelType", errorMessage);
        }
    }

As you can see, for each model you have an if statement. This works fine if you only need to create 2 or 3 validators but if you need more your code will get bigger and bigger and will be harder to read/maintain. The same applies to switch statements.

The first step to solve this problem is to create a Dictionary to store the validators. The key of the Dictionary will be the type of the model and the value will be a delegate that creates an instance of the validator for that model:

	var validators = new Dictionary<Type, Func<IValidator>>
	{
		{ typeof(Foo), () => new FooValidator() },
		{ typeof(Bar), () => new BarValidator() },
		{ typeof(Xyz), () => new XyzValidator() }
	};

Changing the implementation of the factory to use the dictionary:

    public class ValidatorFactory : IValidatorFactory
    {
        private static Dictionary<Type, Func<IValidator>> _validators =
			new Dictionary<Type, Func<IValidator>> {
            { typeof(Foo), () => new FooValidator() },
            { typeof(Bar), () => new BarValidator() },
            { typeof(Xyz), () => new XyzValidator() }
        };

        public IValidator CreateValidatorFor<T>()
        {
            Type modelType = typeof (T);
            IValidator validator = CreateValidatorFor(modelType);

            return validator;
        }

        public IValidator CreateValidatorFor(Type modelType)
        {
            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }

            Func<IValidator> validatorFunc;

            if (_validators.TryGetValue(modelType, out validatorFunc))
            {
                IValidator validator = validatorFunc();

                return validator;
            }

            string errorMessage = string.Concat("Could not find validator for type ", modelType.FullName);
            throw new ArgumentException("modelType", errorMessage);
        }
    }

That’s it, code looks much nicer now! To configure a new validator just add a new key/value pair to the _validators Dictionary.

Finally, testing the code using NUnit:

	// arrange
	var factory = new ValidatorFactory();

	// act
	IValidator validator = factory.CreateValidatorFor<Foo>();

	// assert
	Assert.That(validator, Is.TypeOf<FooValidator>());