Unblocking Build Failure When Moles Not Installed

I have a solution that references a framework project and its tests.  The test project uses Microsoft Moles.  But I’m not actively working on this framework and neither are most of the users of this solution.  When I build the solution, the build fails because I don’t have Moles installed. 

The type or namespace name 'Moles' does not exist in the namespace ... (are you missing an assembly reference?)

I thought this should be an easy fix and so I did some online searching and couldn’t find a comprehensive answer.  So I’m writing this blog for the next person who encounters this issue.

Option 1: Everyone using this solution has to install Moles

If you want to use this solution, you need to install Moles.  You’ll have to do this anyway if you’re actively working on the tests in the project.   And you’ll have to do this on your build server.  But, all your build issues regarding Moles will be solved and all your tests will run.  If you’re running BVTs that use Moles, this is your only option.  Moles has to be installed for the tests to run.

Personally, I don’t like asking people to install a lot of things on their machine they don’t actually need.  Just because Tom is actively using Moles doesn’t mean Harry should have to install it just to build the solution.  And, not everyone has full control to install whatever they’d like on their build server.

Option 2: Unload the test project

The solution will build, but this is a per-user setting.  And this doesn’t solve the failure to build on the build server.

Option 3: Modify the project references

Make a local copy of the Moles dlls shipped in Moles referenced in your project and manually edit the project references to point to your local copy

For example, change:

<Reference Include="Microsoft.Moles.Framework, Version=0.94.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

To

<Reference Include="Microsoft.Moles.Framework">     
<HintPath>$(SolutionDir)External\MolesAssemblies\Microsoft.Moles.Framework.dll</HintPath>
</Reference>

And for the dlls generated by Moles – for example I have a Mole for my Msn.TomsFramework class with the following reference:

<Reference Include=" Msn.TomsFramework.Moles, Version=1.0.15336.204, Culture=neutral, processorArchitecture=MSIL"/>

I don't want to use a HintPath for these because I'll break the project for users actively working on the project with Moles.  Instead, I copied an instance of the generated dll (Msn.TomsFramework.Moles.dll) alongside the Moles definition file (Msn.TomsFramework.moles).  I store these in my $(SolutionDir)Moles directory.

And I added a BeforeBuild target to my project file to copy all those dlls to the bin folder so the project can find the references and build

<Target Name="BeforeBuild">   
<ItemGroup>
<MolesDLLsToBeCopied Include="$(SolutionDir)Moles\*.dll" />
</ItemGroup>
 <Copy SourceFiles="@(MolesDLLsToBeCopied)" DestinationFolder="$(OutDir)" ContinueOnError="true" />
</Target>

updated for MSBuild for .NET 4 (Thanks, Shaun!)

  <Target Name="CopyMolesGeneratedTypes" BeforeTargets="BeforeBuild">
    <ItemGroup>
      <MolesDLLsToBeCopied Include="$(SolutionDir)Moles\*.dll" />
    </ItemGroup>
    <Message Importance="high" Text="Copying generated types for Moles" />
    <Copy SourceFiles="@(MolesDLLsToBeCopied)" DestinationFolder="$(OutDir)" ContinueOnError="true" />
  </Target>

Now this project builds on my machine and the build server without having Moles installed.  It is important to note that the tests do not pass as Moles requires GAC-ed assemblies to run correctly.  So if you can’t install Moles on your build server, you’ll want to remove the Moles tests from your BVTs.