State Street Gang
.NET, straight up

MoQs RoX

June 27, 2008 11:07 by Will

After the big refactor last iteration we're working on the unit tests.  One of the things I wanted to get done was to replace all our lousy stubs (none of which would compile now after the refactor) with a true mock framework.  When considering framework candidates, I had three requirements:  First, it had to be easy to learn and use.  Second, it had to be fully compatible with .NET 3.5 (i.e., using expression trees instead of strings to set expectations).  Third, it had to be free. 

The two candidates I chose are Rhino Mocks 3.5 and MoQ 2.5.  Because MoQ is fully documented (Rhino's 3.5 is a massive change, so all of the documentation out there for the previous versions is useless) I went with MoQ.  I still have Rhino as a reference just in case MoQ can't handle something.  I haven't found one yet.

More...

Tags:
Categories: MoQ | Testing
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

InternalsVisibleToAttribute and Strong Named Assemblies Step by Step

April 9, 2008 12:17 by Will

One of the hassles with testing is that best practices and OO design often makes it very difficult to thoroughly test your code.  We should be marking classes internal to our assemblies unless we specifically wish them to be part of the public API of our DLL's.  This means to test these internal classes we have to use proxy classes that can instantiate and invoke members of these internal classes via reflection.  Visual Studio provides for some auto-generated code for this, but it can be a bit unwieldy and is not available in all versions of VS.  It would be easier if we could specify a test assembly as having access to all these internal classes.

Another case where we might want to make our internal classes available to specific outside callers is for security purposes.  If we don't want anyone but ourselves to use a specific DLL, we would want to mark all classes internal to the DLL and specify only those assemblies with our strong name have access to them.

The InternalsVisibleToAttribute allows us to do this.  According to the documentation, the syntax is pretty easy:

[assembly: InternalsVisibleTo("MyTestsLol")]

This would allow assembly MyTestsLol.DLL access to the internal classes of the assembly where this attribute is located.  And this works great.  For unsigned assemblies only.  When you sign the assembly you wish to mark with this attribute, things get more complex.

Lets say you have two assemblies, My.DLL and MyTestsLol.DLL.  You add the above attribute to the AssemblyInfo.cs file within the My.DLL project.  Everything works great; you can access and test all internal classes in My from within MyTestsLol.  But you're moving to a production oriented environment and you decide that you should be signing your assemblies, because you've read that's what professional .NET developers do.  So you sign My.DLL and build the project:

Friend assembly reference 'MyTestsLol' is invalid. Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations.

Now you're screwed.  And if you Google this, you'll still be screwed because most of the information about InternalsVisibleTo and strong named assemblies is either wrong or too cryptic to understand.  If you find yourself at this point, here is the step-by-step procedure how to get this working again.

Gimme three steps to fix

image First, you will need to sign every assembly you wish to grant access to your internals.  Open up the properties editor for the assembly you wish to give access to, in this case MyTestsLol.DLL, and select the Signing tab.

I'd suggest creating a new, throw-away key pair for test assemblies.  For assemblies you are going to distribute you should use your regular key pair.

Second, you must extract the public key from the public/private key pair, then display the public key.  This is a two-part process that is necessary in order to get the correctly encoded version of the public key. 

Open the Visual Studio command prompt (All Programs -> Visual Studio 2005/8 -> Visual Studio Tools).  Browse to the directory where the new public/private key pair is located.  At the prompt, enter the following command (the name of the key pair (.snk) may be different if you chose a different name for the strong name key file):

sn -p fortestsonly.snk publickey.pub

This creates a file, called publickey.pub, that contains the public key portion of the public/private key pair in binary format.  Next, you need to view the public key in an encoded format (I believe its Base64) that you can use.  Do this via the following command:

sn -tp publickey.pub

This displays both the full public key and the public key token, which is a much smaller hash of the full public key.  You'll need the full public key (the token will not work), so select it and copy it out of the console.  Consoles suck, so you'll have to remove all the newline's when you paste it into your assembly. 

Finally, adjust your InternalsVisibleTo argument to add the public key (the public key should reside on a single line and be roughly three hundred something characters long):

[assembly: InternalsVisibleTo("MyTestsLol, 
    PublicKey=0024...8db5")]

The ellipsis is just to keep the key from blowing up my blog's layout. 

This will now work, and you can reference internal types from the MyTestsLol assembly.  Unfortunately, there isn't an equivalent attribute you can place on a type to allow its internals be visible to another type or another assembly, which would have made unit testing private methods a snap.  I'm not sure exactly why we don't have this kind of facility in the .NET platform.  Maybe in 4? 

kick it on DotNetKicks.com
Tags:
Categories: CLR | Testing | Tips
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Can't save results of the run since ResultFilePath is null.

February 21, 2008 11:12 by will

I've been hit by this lovely error a number of times over the past year when attempting to run unit tests in Visual Studio 2005.  I always end up searching for the answer, encountering the fifty or so different "solutions" that fail horribly.  So now I save it here.

The fix is to reset your environment in Visual Studio.  You can do this by opening a Visual Studio Command Prompt (MS Visual Studio 2005 -> Visual Studio Tools from the start menu) and run the following command (PLEASE READ ON prior to running this!  Important stuff comes later!):

devenv /resetuserdata

This brings Visual Studio back to the primordial stage.  Unfortunately, you lose all your settings.  That includes all your tricky VS fonts and colors customizations.  You won't lose your Add-ins, however.  So if you want to save and then reload all your UI customizations, you'd better save them first. 

For some info about saving color and font settings, you can check out this post over at CodingHorror.


Tags:
Categories: Debug | Testing | Tips
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

C# Next: How about some integral testing support?

January 4, 2008 15:14 by Will

So I'm sitting here at work, reviewing mock frameworks like Rhino Mocks and TypeMock for use in our unit tests, when an actual useful idea for the next verison of the CLR pops into my head. 

One of the problems with unit testing is that the requirements of the tests are often polar opposite of object oriented best practices.  Some of these, like data hiding, are relatively easy to overcome in .NET using features such as reflection.  Others aren't so easy to deal with. Im in ur code mockin ur objex

For instance, say you have a sealed class in your application that doesn't implement an interface.  How do you mock that class?  The TL;DR answer to that question is that you can't do it without rewriting your class or using expensive and complicated testing tools.  The second option is often out of the question with small shops like mine.  The first option is viable, but complicates your code and can end up breaking some OO principles or best practices to do so. 

What would be real slick is if the CLR team provided some first class support for testing.  For the example above, it could be the ability to override sealed to allow classes to be extended for mocking.  Another feature might be a SuperNew, that allows child classes to override base class methods even when the object is cast to the base class type.  Yet another may be allowing extension methods to replace methods in an object.  That might be the simplest way of all to mock an object.  Combine the replacement methods with classes designed to record method arguments and play back return values and unit testing becomes a breeze.

These changes, of course, can be a security and stability risk.  But so can using reflection to manipulate private object fields.  But there isn't any reason why these facilities can't be turned on and off via, for example, compiler switches.  In this case, it could be as easy to control as setting a flag within a configuration (say Debug). 

Ah, well, we can dream, can't we?  Perhaps the CLR team will concentrate on some other important additions to the platform, like cupholders and vibrating, heated seats. 


Tags:
Categories: Testing
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed