“Could not find assembly” Error in Command-line MSTest Execution

One of my tasks today is to get continuous integration running on a Jenkins server. It didn’t take too long to wrestle MSBuild to the ground and get the build working properly, but when I added an MSTest task, a bunch of unit tests failed with this error:

System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.

The System.Web.Providers assembly is properly referenced in the unit test project (it’s part of a NuGet package), and the assembly’s Copy Local property is set to True.

When the unit tests run from inside Visual Studio 2013, they all work. When ReSharper runs them, they all work. But when I execute the command line:

MSTest.exe /resultsfile:MSTestResults.trx /testcontainer:My.Stupid.Test\bin\My.Stupid.Test.dll /test:MyFailingTest

…it fails with the error I noted above.

I’ll spare you the detective work, because I have to get back to work, but I did find the solution. I marked the failing test with aDeploymentItemAttribute:

[TestMethod]
[DeploymentItem("System.Web.Providers.dll")]
public void MyFailingTest()
{
  try
  {
    DoSomeTestyThings();
  }
  finally
  {
    CleanUp();
  }
}

Now, suddenly, the command line works. It’s a total hack, of course, but sometimes we do these things.

Except now, ReSharper is failing to run the tests. So now it takes some digging.

Again, cutting out the 90 minutes of infuriating debugging, the code above didn’t actually solve the problem. It turned out that MSBuild simply didn’t know it had to pull in the System.Web.Providers assembly from somewhere. Fortunately, this guy suggested a way to do it.

I created a new file called AssemblyInit that looks like this:

using System.Diagnostics;
using System.Web.Providers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyApp
{
  public class AssemblyInit
  {
    [AssemblyInitialize]
    public void Initialize()
    {
      Trace.WriteLine("Initializing System.Web.Providers");
      var dummy = new DefaultMembershipProvider();
      Trace.WriteLine(string.Format("Instantiated {0}", dummy));
    }
  }
}

That does nothing more than create a hard reference to System.Web.Providers, causing MSBuild to affirmatively import it.

Now all my CI build works, the unit tests work, and I can go have a weekend.