Testable object wrapper

By | 2014-03-12

Have started experimenting with a way of wrapping the ‘system under test’ in a wrapper-class that also contains the mocked dependencies. The class is instantiated the same way as Brad Wilson’s Testable Object Pattern with a static Create method.

The big difference from his pattern is that the system under test is a public Sut-property instead of using inheritance. The Create method instanciates mocks for the dependencies and creates the system under test with reflection, so less boilerplate code for you to write.

The problem I have with inheritance here is that you kind of pollute your class you wish to test with other stuff. And what I like about putting the system under test as property is you can add fluent methods to your wrapper class making the tests easier to read and understand.

For example:

            //Arrange
            const string userName = "Mats";
            const string emailAddress = "mats@nospam.com";
            var userRepository = new Mock<IUserRepository>();
            var mailer = new Mock<IMailer>();
            var user = new Mock<IUser>();

            user.Setup(m => m.EmailAddress).Returns(emailAddress);
            userRepository.Setup(m => m.Get(userName)).Returns(() => user.Object);

            var sut = new ResetPassword(userRepository.Object, mailer.Object);

            //Act
            sut.Reset(userName);

            //Assert
            userRepository.Verify(d => d.Get(userName));
            mailer.Verify(d => d.SendMail(emailAddress));

Arrange is a bit noisy, and it’s not easy to see that the mock for user is not something the SUT is depending on, ResetPassword-class only depends on IUserRepository and IMailer.

Using the generic Testable object wrapper-class (called Tester) you then easily implement a wrapper with:

    public class ResetPasswordTester :
        Tester<ResetPasswordTester, ResetPassword, IUserRepository, IMailer>
    {
        public Mock<IUserRepository> UserRepository { get { return Param1; } }
        public Mock<IMailer> Mailer { get { return Param2; } }

        public ResetPasswordTester WithUser(string userName, string emailAddress)
        {
            var user = new Mock<IUser>();
            user.Setup(m => m.EmailAddress).Returns(emailAddress);

            UserRepository.Setup(m => m.Get(userName)).Returns(() => user.Object);
            return this;
        }
    }

The generic parameters are: the class itself (so Create-method returns correct instance), System under test (ResetPassword)  and one or more dependencies (IUserRepository, IMailer).

First dependency is first parameter, second dependency is second parameter. Tester automatically creates a instance of the system under test as a “Sut”-property.

Also added a fluent method (.WithUser(…) )that all tests for ResetPassword could use.

This gives you very clean and readable tests.

Another great effect is that if your class takes another dependency then you only have to change the signature of the wrapper and all tests using that wrapper work without any modification to the tests.

The first example could be refactored to look something like this:

            //Arrange
            const string userName = "Mats";
            const string emailAddress = "mats@nospam.com";

            var tester = ResetPasswordTester
                .Create()
                .WithUser(userName, emailAddress);

            //Act
            tester.Sut.Reset(userName);

            //Assert
            tester.UserRepository.Verify(d=>d.Get(userName));
            tester.Mailer.Verify(d => d.SendMail(emailAddress));

Attached to this post is a simple implementation using Moq, and the dummy ResetPassword test class. Replacing Moq with something else like NSubstitute, FakeItEasy is extremely simple.

TestableObjectWrapper

 

Leave a Reply

Your email address will not be published. Required fields are marked *