Manually Creating a Visual Studio .accessor File

Visual Studio 2008 offers a great suite of testing tools for developers. One of the the nicest things is the ability to generate reflection based accessor assemblies that let you access the private members of classes. There is still open debate about the benefit of testing private methods but for some things -- especially security related -- where it makes a great deal of sense. Getting at those private methods however is not the easiest thing to do.

For one-offs you can use reflection directly. Writing your own reflection routines quickly becomes over-verbose and prone to errors. Take this class for example.

class Untestable
{
    private int CantTouchMe()
    {
        return -1;
    }
}

To test Untestable.CantTouchMe by using reflection you'd have to do this:

Assembly assembly = Assembly.Load( "Untestables" );
Type type = assembly.GetType( "Untestable" );
object untestable = Activator.CreateInstance( type );
object result = type.InvokeMember( "CantTouchMe", 
                                   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, 
                                   null, 
                                   untestable, 
                                   null );
Assert.AreEqual( --1, Convert.ToInt32( result ) );

Which is far from ideal and a little less than clear. Instead you can use the new PrivateObject class to make it a bit easier and a lot more clear.

PrivateObject po = new PrivateObject( "Untestables", "Untestable" );
object result = po.Invoke( "CantTouchMe" );
Assert.AreEqual( -1, Convert.ToInt32( result ) );

While it still can be a bit confusing to the next developer reading over the code, it's quite a bit more concise than the manual reflection method. Again for one-offs that's not bad, but writing this code for each private class is tedious. You also run into problems when refactoring since it's all string based. With accessors you can make your life a lot easier.

CantTouchMe_Accessor testObject = new CantTouchMe_Accessor();
Assert.AreEqual( -1, testObject.CantTouchMe() );

Now we have a clear test that is easy to understand and we don't have to write any access classes ourselves. The difficulty is -- how do you get those XXXX_Accessor classes? Using the testing tools in Visual Studio 2008 you get those for free when you ask it to add a unit test for a private class or method. When Visual Studio (or MSBuild) finds an .accessor file it will generate an assembly named TargetAssembly_Accessor.dll that exposes all classes and methods as public. But if you use one of the other popular testing frameworks like nUnit or xUnit.net you have to do it manually.

The first step is to create an .accessor file. This is a plain test file that simply lists the assemblies you'd like to create accessors for -- one per line.

Untestables.dll

The next step is to add it to your Visual Studio project. This is where things get a bit tricky. Simply including a file with an .accessor extension will not cause anything special to happen. Instead you have to change the Build Action to Shadow. Normally you'd be able to do this directly in the IDE, but if you do you'll get property exception instead :(. But the workaround is simple. Right click on the project and select Unload Project. Right click again and select Edit UntouchableTests.proj. Find the <ItemGroup /> that includes your .accessor file and change the tag to <Shaddow />.

<ItemGroup>
  <Shadow Include="Test References\Untouchables.accessor" />
</ItemGroup>

Save, then right click the project and select Reload. Build the project. And you now have your accessor classes.

Related Articles

Published : Mar 18, 2009
Views : 24013

Subscribe Subscribe | Blog Home

Downloads

Tags

  • code
  • development
  • test