Tuesday, June 5, 2012

Moq and IoC experiments

Hello all. It's been a while since I wrote something, why not restart with some interesting piece of code? I've embraced the whole TDD (Test Driven Development) movement and felt the need to use a mocking framework. What is does for you is basically mock the dependencies of the code you want to test, this way, you're not worried about your code accessing a service or a database, you just test your code and ignore the rest, as you're supposed to. Moq does this pretty well, imagine you have:
interface IMyClass
{
  int GetValue;
}

class MyClass : IMyClass
{
  int GetValue()
  {
    //goes to a service or database to come up with this value of 10
    return 10;
  }
}
To test your code, you don't need to execute the logic within GetValue, because your test subject is something else, so, you want to mock the behaviour of GetValue, so it returns a predefined value, and move on. You can do it with Moq, like this:
var myObject = new Mock<IMyClass>();
myObject.Setup(obj => obj.GetValue()).Returns(preDefinedValue);
This creates a new mocked instance of an object implementing your interface, IMyClass, and sets the return value of its method to what we need, so in order to use it, we just use the Object property of the mocked object, which gives us something of type IMyClass:
myObject.Object
Use case for this? imagine you have this code to get tested:
public bool ComputeSomething(IMyClass computerInstance)
{
  //do some calculations

  //you don't really care of what's coming from here,
  //you just want to test the code around it
  int returnValue = computerInstance.GetValue(); 
  //so some more calculations 
  return true|false;
}
This way, you could easily test this, right? Now, to go the extra mile with this, you could even use something like AutoFixture, that provides a plugin for Moq, so you can't use IoC to inject these mocked instances onto your test subjects classes, so easily as:
//Class1 looks like:
public class Class1
{
    private readonly IMyClass _obj;

    public Class1(IMyClass obj)
    {
        _obj = obj;
    }

    public int CalculateStuff()
    {
        int i = _obj.GetThatInt();

        return i * i;
    }
}


private IFixture _fixture;

[TestFixtureSetUp]
public void SetUp()
{
    //init autofixture
    _fixture = new Fixture().Customize(new AutoMoqCustomization());

    //setup our IMyClass dependencies, only once
    var myClassMocked = _fixture.Freeze<Mock<IMyClass>>();
    myClassMocked.Setup(x => x.GetValue()).Returns(10);

    //so here we have frozen a IMyClass instance on the fixture, so when we ask for something depending on it in the future from the fixture, it will auto inject this froze instance on it
}

[Test]
public void Test_that_method_from_CL()
{
    //ask autofixture for a Class1 instance with its dependencies mocked
    //and it provides, automatically, injecting the frozen IMyClass mock into Class1's contructor
    var cut = _fixture.CreateAnonymous<Class1>();

    //act & assert
    Assert.That(cut.CalculateStuff(), Is.EqualTo(100));
} 

No comments: