Released AutoWrockTestable: Making test class composition easier / by Matt Wrock

birdLate last year I blogged about a unit testing pattern I have been using for the past couple years. It’s a pattern that I initially learned from Matt Manela (@mmanela). I adapted the pattern to use Automocking with Richard Cirerol’s wrapper. Over the last week I have been working to plug this in to Visual Studio as a template that can easily add test classes and make one’s unit testing work flow more efficient.

I could, should, maybe will, but probably won’t write a separate post dedicated to making the Visual Studio extension. Ironically, while I am a member of the Visual Studio Gallery team, this is my first public extension I have written. While it is a trivial extension as extensions go, there were some interesting learnings that made what I thought would be a couple night’s worth of work into a week of my spare time. Despite some frustrating incidents, it was a lot of fun.

Now lets dive into AutoWrockTestable!

Whats better than AutoMocking? Why of course, AutoWrocking!

Visual Studio integration makes composing tests a snap!

Here is how to effortlessly add test classes to your solution with all mockable dependencies mocked:

1. You can download The Visual Studio Extension from Codeplex or the Visual Studio Gallery.
The extension will also install Nuget if you do not already have it and will add Structuremap, Structuremap.Automocking and Moq to your Nuget repository.

2. Create a skeleton of your implementation class.

public class OAuthTokenService{    private readonly IWebClientWrapper webClientWrapper;    private readonly IRegistryWrapper registry;

    public OAuthTokenService(IWebClientWrapper webClientWrapper,        IRegistryWrapper registry)    {        this.webClientWrapper = webClientWrapper;        this.registry = registry;    }    public string GetAccessToken(string clientId, IOauthUrls oauthUrls)    {        return null;    }}

3. Click on the "Add Testable..." menu item in Solution Explorer's "Add" context menu.


4. Enter the name of the class you want to test. You can enter any name but the text box will auto complete using all class files open in the editor. The first class in the active file is initially selected.


5. AutoWrockTestable creates a new class file with the same name as your implementation class appending "Tests" to the name and containing this code:

using AutoWrockTestable;

namespace SkyCli.Facts{    class OAuthTokenServiceTests    {        class TestableOAuthTokenService : Testable<SkyCli.OAuth.OAuthTokenService>        {            public TestableOAuthTokenService()            {

            }        }    }}

Writing tests using Testable<ClassToTest>

The Testable class has its dependencies automatically mocked. Now you can start to write test methods using your Testable. I like to use nested classes (a class for every method I want to test) to organize my tests. Here is how a test might look:

class OAuthTokenServiceTests{    class TestableOAuthTokenService : Testable<SkyCli.OAuth.OAuthTokenService>    {        public TestableOAuthTokenService()        {

        }    }

    public class GetAccessToken    {        [Fact]        public void WillReturnTokenFromRegistryIfAFreshOneIsFoundThere()        {            var testable = new TestableOAuthTokenService();            var registryValues = new Dictionary<string, string>();            registryValues.Add("access_token", "token");            registryValues.Add("expires_in", "3600");            registryValues.Add("grant_time", DateTime.Now.Ticks.ToString());            testable.Mock<IRegistryWrapper>().Setup(x => x.GetValues("path"))                .Returns(registryValues);

            var result = testable.ClassUnderTest.GetAccessToken("clientId", null);

            Assert.Equal("token", result);        }    }}

See Using the Testable<T> Class for a complete explanation of the Testable<T> API.

For more information on the Testable pattern and Auto Mocking in general see The Testable Pattern and Auto Mocking Explained or see my previous blog post on the subject.