Tag Archives: testability

Refactoring a static class with hard-coded dependencies for testability

is not that hard. You can add a factory method to the static class to create the dependency, and change the factory method at test-time.
Here’s an example:

public static class WithDependencies
{
	public static string MethodWithDependencies()
	{
		using (var thing = new HardCodedThing())
		{
			return DoSomething();
		}
	}
}

which can be turned into:

public static class WithDependencies
{
    public static Func<HardCodedThing> CreateHardCodedThing = () => new HardCodedThing();

	public static void MethodWithDependencies()
	{
		using (var thing = CreateHardCodedThing())
		{
			DoSomething();
		}
	}
}

With this code in your test:

[TestFixture]
public class WhenDoingSomething
{
	private Mock<HardCodedThing> mockThing;

	[SetUp]
	public void SetUpMockThing()
	{
		// mockThing.Setup( ...  ) ... etc ...
	}

	public void Given_hardcodedthing_does_X_should_get_Y()
	{
		//Arrange
		WithDependencies.CreateHardCodedThing = () => mockThing.Object;
		//Act
		var result= WithDependencies.MethodWithDependencies();
		//Assert
		Assert.AreEqual("Y", result);
	}
}

NUnit Constraints Example – a Simple Custom Constraint

Are you short of an NUnit Assertion? You have some code for a test, but you really want it in NUnit constraint form so you can use it like any other test. They are easy to write. Here’s an example which wraps a function you already wrote as a Constraint:

public class EqualsByValueConstraint : Constraint
{
	private readonly object expected;
	private CompareResult compareResult;

	public EqualsByValueConstraint(object expected)
	{
		this.expected = expected;
	}

	public override bool Matches(object actual)
	{
		this.actual = actual;
		compareResult = EqualsByValueOrFailureReason(actual, expected);
		return compareResult;
	}

	public override void WriteDescriptionTo(MessageWriter writer)
	{
		writer.WriteExpectedValue(this.expected);
	}
	public override void WriteActualValueTo(MessageWriter writer)
	{
		base.WriteActualValueTo(writer);
		writer.WriteLine();
		writer.WriteMessageLine("Compare Result " + compareResult);
	}
}
public class CompareResult
{
	public bool IsPass {get;set;}
	public string FailureDescription {get; set;}
}

If your function is just a boolean, then you could remove the CompareResult class. The drawback being that your failure message will only say ‘failed’ rather than give an explanation of the failure. In that case, you might just as well not use the constraint and use the Assert.That(bool, message) overload.

A Very Small Editable PDF for Testing

A Small PDF

Ever wanted a small PDF file, or to tweak your own PDF for testing? Below is a very small PDF which you can paste into a text editor and save as MySmallPdf.PDF.
Two things are easy to edit:

  • The page size. Look for the line /MediaBox [0 0 612 144]. Leave the first (0,0) pair and edit the (612,144) to be (width of page,height of page) in 1/72ths of an inch.
  • One line of text. Look for the line (This is a small text editable pdf) Tj and replace the text with your own.

This is particularly helpful if you are testing http://itextpdf.com/ or itextsharp or some other PDF generator or API, and you want a couple of small identifiable test files to play with.

The Editable PDF

%PDF-1.4
1 0 obj
<< /Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<< /Type /Outlines
/Count 0
>>
endobj
3 0 obj
<< /Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<< /Type /Page
/Parent 3 0 R
/MediaBox [0 0 612 144]
/Contents 5 0 R
/Resources << /ProcSet 6 0 R
/Font << /F1 7 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 73 >>
stream
BT
/F1 24 Tf
100 100 Td
(This is a small text editable pdf) Tj
ET
endstream
endobj
6 0 obj
[/PDF /Text]
endobj
7 0 obj
<< /Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000364 00000 n
0000000466 00000 n
0000000496 00000 n
trailer
<< /Size 8
/Root 1 0 R
>>
startxref
625
%%EOF

The PDF ISO32000 standard

The PDF reference is available for free from Adobe at http://www.adobe.com/content/dotcom/en/devnet/pdf/pdf_reference.html The one you want is the copy of the ISO reference at http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf

dotCover config file for command line NUnit test coverage

So you want to produce a coverage report for your .Net project, preferably from the command line? If you use dotCover and NUnit then this:

<?xml version="1.0" encoding="utf-8"?>
<AnalyseParams>
    <Executable><!-- Path to your NUnit bin directory e.g.  -->C:\Program Files\NUnit 2.5.10\bin\net-2.0\nunit-console.exe</Executable>
    <WorkingDir><!-- This path works for running dotCover with a config file in the project directory-->bin\Debug\</WorkingDir>
    <Arguments><!-- The dlls containing NUnit tests. Space delimited if more than one-->My.Tests.dll My.MoreTests.dll</Arguments>
    <Output><!-- Path to where I want the report. Can be relative or absolute -->My.Tests.Coverage.html</Output>
    <Filters>
        <IncludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>*</ModuleMask></FilterEntry>
        </IncludeFilters>
        <ExcludeFilters>
            <FilterEntry><!--  _ "Module" means project _ --><ModuleMask>My.Tests</ModuleMask></FilterEntry>
            <FilterEntry><!-- namespaces can be filter with a ClassMask with * wildcard --><ClassMask>Namespaces.For.AutogeneratedCode.*</ClassMask></FilterEntry>
            <FilterEntry><ClassMask>SomeUntestable.Class</ClassMask></FilterEntry>
        </ExcludeFilters>
    </Filters>
    <ReportType>html</ReportType>
 </AnalyseParams>

will allow you, from the command line, to type:

dotCover analyse MyConfigFileName.xml

and generate coverage reports. Assuming that dotCover is in your path of course.
I like to set the filters to exclude coverge report on the test project itself as well as autogenerated code.

Covering Multiple Test Projects In One Run

  • Set your working directory to be a parent of all the test projects, e.g. the solution directory.
  • List the full relative paths to each Test dll, space limited:
    <WorkingDir>.</WorkingDir>
    <Arguments>Web.Tests\bin\Debug\MyProject.Web.Tests.dll Implementation.Tests\bin\Debug\MyProject.Implementation.Tests.dll</Arguments>

Filtering and more advanced coverage configs

  • Look down the right hand side of the page here : http://www.jetbrains.com/dotcover/documentation/index.html for documentation, such as it is.
  • Filtering is covered here: http://blogs.jetbrains.com/dotnet/2010/07/filtering-with-dotcover/
  • More complex stuff is touched on here: http://blogs.jetbrains.com/dotnet/tag/code-coverage/

The Object Quote Pattern for Testability of Components with Dependencies

I hereby introduce a very simple no-configuration pattern for making components with dependencies unit testable. Object Quote competes with existing solutions for testability of components with dependencies and is intended to be the simplest possible solution. This will make most sense if you already understand the problem of unit testing components and classes with dependencies.

Existing Patterns for Unit Testability

  • Dependency Injection or Service Location use a DI Container or a Service Locator for runtime configurability. As a side effect, they also provides a solution, albeit rather heavyweight, for test-time mockability
  • The Humble Object Pattern is an approach for codebases built without DI or service locator. A class with dependencies is refactored into two classes, one of which sets up the dependencies on the other, which contains the meat (or logic) of the class. The class containing the logic is then testable.

Neither of these are cost-free. Dependency Injection requires a framework and is best considered as an application-wide architectural pattern that should be used when runtime configuration is required. In that sense it is overkill for most bespoke code where you don’t need to choose at runtime between multiple implementations for an interface, and all you want is test-time mockability.

The humble object is effectively a proposal to rewrite code, albeit minimally. So it has a significant cost to it; and the end result is slightly more complex than the original.

The Object Quote Pattern

is very simple. It requires no framework, and can be applied to existing code for virtually no startup cost.

  1. Merrily write (or read, if it’s already written) your code with hard coded dependencies.
  2. Uncouple the dependencies by quoting the hard-coded references with a “Soq” – a simple object quoter.
  3. In your unit tests, configure the Soq as a Moq Soq.

Behold. You now have decoupled, testable code. Thus:

public class MyClassThatDependsonSomething
{
	public SomeDependency  D1 { get; set; }

    public MyClassThatDependsonSomething()
    {
        D1 = Soq.Quote( new SomeDependency() );
    }
}

[TestFixture]
public class TestExampleCode
{
    [Test]
    public void Test_something_with_dependencies()
    {
        //Arrange
        SomeDependency dummy = new Mock<SomeDependency>().Object;

        var mockSoq = new Mock<Soq>();
        mockSoq.Setup(soq => soq.QuoteImplementation<SomeDependency>(It.IsAny<SomeDependency>()))
                .Returns(dummy);
        Soq.ConfigureForTest(mockSoq.Object);

        // Act
        var myClass = new MyClassThatDependsonSomething();
        var result = myClass.D1;

        //Assert
        Assert.AreSame<SomeDependency>(dummy, result);
    }
}

How it works

By default the Soq just returns the object given it.
But when configured for test, the Soq is implemented by your MoqSoq, which returns whatever you’ve configured it to.

Voila. Testable code with no framework needed and no extensive refactoring of existing codebase. You get started with TDD even on legacy code with minimal overhead.

Get the code and a couple of example tests from https://github.com/xcarroll/Soq. Or copy and paste the source — just 12 lines of actual code  — from below.

The Soq Class

On Github: https://github.com/xcarroll/Soq/blob/master/Soq.cs

using System;
public class Soq
{
        private static Soq instance = new Soq();

        public static T Quote<T>(T instantiatedDependency)
        {
            return instance.QuoteImplementation<T>(instantiatedDependency);
        }

        public virtual T QuoteImplementation<T>(T dependency)
        {
            return dependency;
        }

        public static void ConfigureForTest(Soq testSoq)
        {
            if (!ConfigurationIsEnabled)
            {
                throw new InvalidOperationException(
                 "Test configuration is not enabled.");
            }
            instance = testSoq ?? new Soq();
        }
        public static bool ConfigurationIsEnabled { get { return true; } }
}