Archive

Archive for the ‘Agile’ Category

Using Rhino Mocks with Void (or ‘Sub’) Methods

July 22nd, 2008 Scott Lilly Comments off

I ran into a bit of trouble the other day when I was writing a test with Rhino Mocks.  It took a while to find the solution, so I figured I’d post it here for anyone else looking to do the same thing.

The problem I had was trying use a mock object for my data access layer, and calling a void method on the class.  There are thousands of examples of how to mock a method call that returns a value, but it took a while to find out how to handle a method call that doesn’t return anything.  In my test below, if the method returned something, I’d use code like this:

using ( mockery.Record() )
{
   Expect.Call( dal.ExecuteQuery( null ) ).IgnoreArguments().Return( results );
}

For a void method (or ‘Sub’, instead of ‘Function’, for the VB.Net developers), you need to set up a delegate instead. See the line that calls “ExecuteNonQuery” for an example.

[Test]
public void CreateNewUserStory()
{
   MockRepository mockery = new MockRepository();
   IDataAccessor dal = mockery.CreateMock<idataaccessor>();

   IUserStoryControl screen = mockery.Stub<iuserstorycontrol>();
   UserStoryController controller = new UserStoryController( dal );

   screen.StoryTitle = “Test title”;
   screen.Description = “Test description”;

   using ( mockery.Record() )
   {
      Expect.Call( delegate { dal.ExecuteNonQuery( null ); } ).IgnoreArguments();
   }

   using ( mockery.Playback() )
   {
      controller.CreateNewUserStory( screen );
   }

   Assert.AreEqual( “”, screen.StoryTitle );
   Assert.AreEqual( “”, screen.Description );
}

Categories: Agile, Development, Mock Objects, Testing Tags:

Unit Testing Legacy Code with Dependency Injection and Mock Objects – Part III

January 24th, 2008 Scott Lilly Comments off

Unit Testing Legacy Code with Dependency Injection and Mock Objects – Part III

In the last post, we got to the point where we can do dependency injection of the web service object. Now we’ll actually do some injection, using mock objects for unit tests. For this demonstration, I’ll be using NUnit for the unit test framework. This would work just as well (with minor syntax changes) for Microsoft’s unit testing framework. I’ll also be manually creating the mock objects that will be used for the tests. There are some libraries out there that will give you a whole framework for mocking classes, but I think that using the manually created classes (and seeing their source code) will be a bit clearer. If you’re interested in the mocking libraries, check out NMock, RhinoMock, and TypeMock.

The first thing to do is install the tools we need for unit testing. NUnit is what I generally use. I also use TestDriven.Net to help with testing. It lets you run your tests while still inside Visual Studio.

Now, we can open up the solution in Visual Studio and create a new ‘class library’ project (TestBusinessObjects) to hold our unit tests. That project needs to have a reference to the BusinessObjects project and another one to ‘nunit.framework’ (which is available under the .Net tab when you add a reference to a project, as long as you’ve installed NUnit). Then we can create our first test class, which I’ll name TestPropertyAddress.cs. The code for the class is listed below.

TestPropertyAddress.cs

using System;

using BusinessObjects;
using NUnit.Framework;

[TestFixture]
public class TestPropertyAddress
{
[Test]
public void SavePropertyAddress_ShouldSucceed()
{
PropertyAddress propAddr = new PropertyAddress();
propAddr.Save( “1234 Main Street”, “Houston”, “TX”, “77777″ );
}
}

The “[TestFixture]” before the class, and the “[Test]” before the SavePropertyAddress_ShouldSucceed() method, designate that these are used for unit testing. Within our test method, we create a PropertyAddress object and attempt to save some data that should be valid. Since Save() has no return value, the test passes as long as no exception is thrown. If we want to test a method that returns a value, NUnit has methods you can call from Assert (see the NUnit documentation for details).

Now, it’s time to create the mock object. I’ll create a MockPropertyAddress class in the TestBusinessObjects project and have it implement the IAddressValidator interface. I’ll also add in a way to let me determine how the mock object should respond when executed. The code for this class is below.

MockAddressValidator.cs

using System;

public class MockAddressValidator : BusinessObjects.IAddressValidator
{
public enum Responses
{
ReturnTrue,
ReturnFalse,
SimulateRealValidation,
ThrowWebException
}

public Responses Response = Responses.SimulateRealValidation;

public bool IsAddressValid( string streetAddress, string city, string stateCode, string zipCode )
{
switch ( Response )
{
case Responses.ReturnFalse :
return false;
case Responses.ReturnTrue :
return true;
case Responses.SimulateRealValidation :
return ( streetAddress != “” &amp;&amp; city != “” &amp;&amp; stateCode != “” &amp;&amp; zipCode != “” );
case Responses.ThrowWebException :
throw new System.Net.WebException();
default:
throw new ArgumentException( “Response was not set to a valid value” );
}
}
}

With this mock class, we can now force our AddressValidator service behave the way we want. We also don’t need to use the real validation service for our tests. Here is the TestAddressProperty.cs class after adding tests for more conditions:

using System;

using BusinessObjects;
using NUnit.Framework;

[TestFixture]
public class TestPropertyAddress
{
[Test]
public void SavePropertyAddress_ShouldSucceed()
{
MockAddressValidator validator = new MockAddressValidator();
validator.Response = MockAddressValidator.Responses.SimulateRealValidation;

PropertyAddress propAddr = new PropertyAddress( validator );
propAddr.Save( “1234 Main Street”, “Houston”, “TX”, “77777″ );
}

[Test, ExpectedException( typeof( ArgumentException ), ExpectedMessage = “Property address is not valid.  Data was not saved.” )]
public void SavePropertyAddress_MissingData_ShouldFail()
{
MockAddressValidator validator = new MockAddressValidator();
validator.Response = MockAddressValidator.Responses.SimulateRealValidation;

PropertyAddress propAddr = new PropertyAddress( validator );
propAddr.Save( “1234 Main Street”, “Houston”, “”, “77777″ );
}

[Test, ExpectedException( typeof( System.Net.WebException ) )]
public void SavePropertyAddress_ValidatorHasWebException_ShouldFail()
{
MockAddressValidator validator = new MockAddressValidator();
validator.Response = MockAddressValidator.Responses.ThrowWebException;

PropertyAddress propAddr = new PropertyAddress( validator );
propAddr.Save( “1234 Main Street”, “Houston”, “TX”, “77777″ );
}
}

When we create the MockAddressValidator class, we have all the properties and methods of the class visible. That lets us use the Response value to set how we want the object to respond when the other code calls it. Since it implements the IAddressValidator interface, we can pass it in through the constructor of the PropertyAddress class. Then, when PropertyAddress.Save() calls the validation web service, it actually calls our mock one, which gives the response we need for tour tests.

So, there is a way to take some legacy code with dependencies and gradually change it to code that can easily be tested. If you have any questions, please leave a comment.

Unit Testing Legacy Code with Dependency Injection and Mock Objects – Part II

January 22nd, 2008 Scott Lilly Comments off

Solution file
Looking at the code from the first post, it works fine (at least for a stripped-down demo). However, there are a few problems with it. If you want to test that the program works, you need to manually run the program, enter some data, and see the results. It’s possible to create some scripts to run the program, but they tend to be fragile and can start breaking if you modify the UI (like changing the “State Code” textbox to a drop-down list). You also need to always be able to contact the third-party web service to do your testing. If the service is down, your test can fail, even though your code is functioning as you expect. You are also dependent on the results returned from the web service. If you are connecting to a test site, they may clean out their database, causing your previously valid input to fail.

A common opinion of unit tests is that they should not require any external resource. I like to think of my program loaded in memory. Anything outside of that memory is an external resource that could potentially fail due to something that isn’t related to the program. If I need to write to disk, the disk may be full or the network may be down. Sending out an e-mail may fail because the mail server has not been set to allow outbound mail from my computer. The Internet may be down, and nobody has a backup copy (well…you know what I mean). You may also have a problem if everything is working. How are you going to test how your program handles the database server being down, other than stopping the database server (which you may not have rights to do)? With mock objects, you create a simulation of these external resources, and you have complete control over how you want them to react.

By the way, I want to be sure to mention that you still need to test how your program works with the real external resources. However, that’s integration testing. Unit testing is just your first round of testing.

In order to make this program testable, we’re going to do some dependency injection, then create mock objects that let us test all our code paths without needing to worry about some other system being stable. Right now, the PropertyAddress class is dependent on the web service. We’re going to invert it by passing the web service object into its constructor.

First we’ll create a new class in the BusinessObjects project. It will be named AddressValidator. The only method it will have on it is the IsAddressValid method that is being used in the PropertyAddress class. This method will call the web service, to do the data validation. The code looks like this:

AddressValidator.cs

using System;

using BusinessObjects.AddressValidationService;

namespace BusinessObjects
{
    public class AddressValidator
    {
        public bool IsAddressValid(string streetAddress, string city, string stateCode, string zipCode)
        {
            ValidationService validator = new ValidationService();
            return validator.IsAddressValid( streetAddress, city, stateCode, zipCode );
        }
    }
}

Next, we’ll modify the PropertyAddress class to start removing the dependency on the web service. There are a few different ways to do this, but I’ll do a fairly simple method. We create a constructor that initializes a private variable that holds this AddressValidator object. Then, we have the Save method use this private variable. The new code looks like this:

PropertyAddress.cs

using System;

namespace BusinessObjects
{
    public class PropertyAddress
    {
        private AddressValidator myValidator;

        public PropertyAddress()
        {
            myValidator = new AddressValidator();
        }

        public void Save(string streetAddress, string city, string stateCode, string zipCode)
        {
            if(myValidator.IsAddressValid(streetAddress, city, stateCode, zipCode))
            {
                // Code to save to the database would go here.
            }
            else
            {
                throw new ArgumentException( “Property address is not valid.  Data was not saved.” );
            }
        }

    }
}

After making these changes, I ran the program and saw that everything is still working. One of my favorite practices of Agile development is making small changes and testing them often. This way, I don’t spend eight hours, writing hundreds of lines of code, then trying to figure out exactly which change caused the program to break. If something stops working, I know it was something I changed in the last few minutes, since all the tests were successful a few minutes ago.

As you probably noticed, the PropertyAddress class is still dependent on the web service. We just moved the instantiation of the web service object to another place (I know I have some smart readers out there). We still need a way to pass in our mock objects. In order to do that, we’ll create another constructor that accepts an AddressValidator object. But, we’ll actually have it accept an interface as the parameter’s datatype. The interface just defines what properties and methods the class needs to have. In the BusinessObjects project, create this IAddressValidator interface:

using System;

namespace BusinessObjects
{
    public interface IAddressValidator
    {
        bool IsAddressValid( string streetAddress, string city, string stateCode, string zipCode );
    }
}

Go back to the AddressValidator class and change the line:

public class AddressValidator

to this, in order to say that this class implements the IAddressValidator interface:

public class AddressValidator : IAddressValidator

Then, go back into PropertyAddress.cs and change the line:

private AddressValidator myValidator;

to this, so that the private variable is a type of the interface:

private IAddressValidator myValidator;

While you’re in PropertyAddress.cs, add a new constructor that takes a parameter of IAddressValidator and assigns it to the private variable. Now, PropertyAddress.cs should look like this:

using System;

namespace BusinessObjects
{
    public class PropertyAddress
    {
        private IAddressValidator myValidator;

        public PropertyAddress( IAddressValidator validator )
        {
            myValidator = validator;
        }

        public PropertyAddress()
        {
            myValidator = new AddressValidator();
        }

        public void Save(string streetAddress, string city, string stateCode, string zipCode)
        {
            if(myValidator.IsAddressValid(streetAddress, city, stateCode, zipCode))
            {
                // Code to save to the database would go here.
            }
            else
            {
                throw new ArgumentException( “Property address is not valid.  Data was not saved.” );
            }
        }

    }
}

We’re now at the point where we have the ability to inject our dependent object into our class. In the next post, we’ll write some unit tests and some mock objects to use in those tests.