Thursday, December 3, 2009

Watin 2.0 and Gallio 3.1 in x64 environment: fixing System.Reflection.ReflectionTypeLoadException and System.Runtime.InteropServices.COMException "The interface is unknown" issues

We use Gallio/MbUnit and Watin at my work for unit testing of an ASP.NET website, as it provides excellent reports including the raw Watin events (click, type, select) and screenshots for failed cases. Today I spent a few hours trying to get the project working on my new Windows 7 x64 development machine, and things did not start out very well. When I first tried to load the project in the Gallio Icarus runner none of the unit tests showed up and it indicated that an exception was thrown while exploring tests. I tried using both the x64 and x86 versions of Gallio/MbUnit, and even tried using the TestDriven.NET loader from within Visual Studio, but couldn’t get anything to work. Here is the full error message for Google’s sake:

[error] An exception was thrown while exploring tests.
Location: D:\SVN_Development\OQA Unit Testing\OQA Testing Framework\OQA Testing Framework\bin\Debug\OQA Testing Framework.EXE
Reference: OQA Testing Framework, Version=, Culture=neutral, PublicKeyToken=null
Details: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. 
   at System.Reflection.Module._GetTypesInternal(StackCrawlMark& stackMark) 
   at System.Reflection.Assembly.GetTypes() 
   at Gallio.Common.Reflection.Impl.NativeAssemblyWrapper.GetTypes() in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Common\Reflection\Impl\NativeAssemblyWrapper.cs:line 72 
   at Gallio.Framework.Pattern.TestAssemblyPatternAttribute.PopulateChildrenImmediately(IPatternScope assemblyScope, IAssemblyInfo assembly) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\TestAssemblyPatternAttribute.cs:line 147 
   at Gallio.Framework.Pattern.TestAssemblyPatternAttribute.Consume(IPatternScope containingScope, ICodeElementInfo codeElement, Boolean skipChildren) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\TestAssemblyPatternAttribute.cs:line 75 
   at Gallio.Framework.Pattern.DefaultPatternEvaluator.Consume(IPatternScope containingScope, ICodeElementInfo codeElement, Boolean skipChildren, IPattern defaultPrimaryPattern) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\DefaultPatternEvaluator.cs:line 153

The error message indicates that it is due to an issue with missing assemblies, and suggested that you make sure the CopyLocal option is set to true for all 3rd party references, but that didn’t help either. Finally I created a test project and started ripping the original project to peaces to find out why it was failing. Turns out it worked fine if I remove a reference to an interface stored in the Watin.Core.Dll assembly, so I setup a workaround and was finally able to load the tests. Only problem was that it would fail whenever the test tried to load Watin. At this point I figured it had to be an issue with the Watin dll, and it turns out that it was simply trying to load an x64 version of the library that doesn’t actually exist (the library is x86 only). This link suggested setting Visual Studio to use x86 as the build platform type instead of “Any CPU”, and once I did that the original project started working. Yay!

It didn’t take long though for something else to fail, as it threw an exception as soon as one of the tests tried to access the Document object. This time the exception was System.Runtime.InteropServices.COMException with Message="The interface is unknown. (Exception from HRESULT: 0x800706B5)" coming from mshtml.HTMLDocumentClass.IHTMLDocument2_get_url(). Another quick search lead to another StackOverflow answer suggesting to run Visual Studio as an Administrator. That seem to do the trick!

So if you are using an x64 machine to do unit testing with Gallio, MbUnit, and Watin, make sure to set the platform to x86 and make sure to run Visual Studio and Icarus as an Administrator! I should probably get back to working on those unit tests now :-P



Greg Bray said...

Fact, even better: Right click on the shortcut that you use to run Visual Studio or Icarus and select properties, then advanced, then "Run As Administrator" to make sure that you don't forget!

Jeff Brown said...

I'll see what I can do to fix this since it should all just work without any fuss. Works for me on Windows 7 x64 anyways.

Greg Bray said...

Well Gallio and MbUnit work fine in x64, but the beta version of Watin doesn't have an x64 version so I think it most likely was an issue with Watin and not an issue with Gallio. It would have been nice though if the error message for missing types was handled better, maybe catch the System.Reflection.ReflectionTypeLoadException and "Retrieve the LoaderExceptions property for more information" as indicated in the error message to give the user more information about which type/assembly caused the error.

If you want to try and test it for yourself setup a .net 2.0 or 3.5 (I tried both) project targeting x64 and try inheriting the WatiN.Core.Interfaces.ILogWriter interface as part of a custom logging class. That is what caused the above error message for me. Also my testing solution is broken down into two projects: one that contains the core logic for using Watin to automate the application, and a second that contains all the unit tests. The first project gets added to the unit test project as a reference, so that may have had something to do with it too, however I did make sure that all the files were being copied correctly.

Let me know if you have any questions, and keep up the great work!

Post a Comment

Blog.TheG2.Net - Your guide to life in the Internet age.