System.BadImageFormatException when using Coherence and Moq - c#

When using the following line in a moq unit test, I get a System.BadImageFormatException.
mockDataAccessLayer.Setup(dal => dal.ListItems(It.IsAny<List<IFilter>>()));
The exception:
System.BadImageFormatException : [C:\Users\ric\AppData\Local\Temp\q3a2acu1.brz\RJ.DAL.test\assembly\dl3\cb8fb82f\e33b012a_c5f6cc01\RJ.DAL.test.DLL] The signature is incorrect.
at RJ.DAL.test.DALLayerTest.DataAccessLayerTest()
The full unit test:
[Test]
public void DataAccessLayerTest()
{
var mockDataAccessLayer = new Mock<IDAL>();
mockDataAccessLayer.Setup(dal => dal.ListItems(It.IsAny<List<IFilter>>()));
var dataAccessLayer = mockDataAccessLayer.Object;
}
I am fairly sure the problem lies with the List of IFilters, as I use very similar code elsewhere without the It.IsAny which works fine. Any ideas?

As Hans mentioned, it was due to missing an assembly for the interface. Adding the dll containing the interface fixed the problem.

Related

Assembly.GetEntryAssembly() in NUnit

I am using NUnit to test one functionality where I need to load XML file to object. The XML file is in location of the Console Application.
I have Following method where configuration will be read :
public string GetConfiguration(TempFlexProcessor processor)
{
var exePath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var configPath = Path.Combine(Path.GetFullPath(exePath), "configuration");
var configFile = string.Format(#"{0}.xml", processor.GetType().Name);
}
Now in my NUnit Test I have test method where I test GetConfiguration :
[Test]
public void TempFlexProcessorExecuteTest()
{
#region Given
#endregion
#region When
var tempFlexProcessor = new TempFlexProcessor();
var actual = tempFlexProcessor.GetConfiguration(tempFlexProcessor);
#endregion
Assert.AreEqual("path of the file", actual);
}
But System.Reflection.Assembly.GetEntryAssembly() is null, please help.
I used AppDomain.CurrentDomain.BaseDirectory instead of System.Reflection.Assembly.GetEntryAssembly().Location
I suspect the problem is that NUnit is running your tests in a different AppDomain, but without using ExecuteAssembly. From the documentation for Assembly.GetEntryAssembly:
Gets the process executable in the default application domain. In other application domains, this is the first executable that was executed by AppDomain.ExecuteAssembly.
It's not clear which assembly you really want to get - even if this did return something "appropriate" for NUnit, that's likely to be the NUnit executable, which would be well away from any configuration directories you happen to have.
Basically, I think that you should at least provide an alternative way of specifying the configuration directory - and you might want to reconsider whether using GetEntryAssembly is a good idea anyway. (Aside from anything else, it's slightly odd that you're calling GetConfiguration on a processor and passing in another processor... that may be suitable for your design, but it's at least somewhat unusual, given that in your test case you're passing in a reference to the same object.)

What does "Method ...ClassInitialize has wrong signature ..." mean?

In my Visual Studio 2012 solution I have a C# project for unit testing C++/CLI code, e.g.
...
using System.IO;
using Stuff;
namespace MyCLIClassTest
{
[TestClass]
public class MyCLIClassTest
{
public MyCLIClassTest() {}
[ClassInitialize]
public static void Setup(TestContext testContext)
{
}
[TestMethod]
public void LibraryAccessTest()
{
...
}
}
}
Now, the C# tests all fail with a message like "Method MyCLIClassTest.MyCLIClassTest.ClassInitialize has wrong signature. The method must be static, public, does not return a value and should take a single parameter of type TestContext."
After removing the ClassInitializer I got "Unable to set TestContext property for the class MyCLIClassTest.MyCLIClassTest. Error: System.ArgumentException: Object of type 'Microsoft.VisualStudio.TestPlatform.MSTestFramework.TestContextImplementation' cannot be converted to type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestContext'..
I used DLLs of older unit testing framework versions. This happened because the project migrated recently to VS2012.
So, in the solution explorer under the test project you find "References". Right click it and select "Add reference..." to open the Reference Manager. Search for "unittest" and check the Microsoft.VisualStudio.QualityTools.UnitTestFramework with version number 10.1.0.0. Un-check all other versions of this assembly. Close the manager by clicking OK.
An alternate answer copied from a duplicate question: Why is a ClassInitialize decorated method making all my tests fail?
The [ClassInitialize] decorated method should be static and take exactly one parameter of type TestContext:
[ClassInitialize]
public static void SetupAuth(TestContext context)
{
var x = 0;
}
I had the exact same issue and removing/adding references as suggested by TobiMcNamobi did not solve it for me, however removing the reference, right click the project and selecting "Add > Unit test..." and thereby getting the reference re-generated worked. Not sure what the difference was compared to doing it manually.
Setup has wrong signature. Parameter 1 should be of type Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.
I was running a Load Test Project and had both v10.0.0.0 versions of the DLLs:
Microsoft.VisualStudio.QualityTools.LoadTestFramework.dll
Microsoft.VisualStudio.QualityTools.WebTestFramework.dll
Changing the version LoadTestFramework to version 10.1 didn't fix it.
I had to goto my Unit Test Project and delete the MSTest.Adapter references:
Microsoft.VisualStudio.TestPlatform.TestFramework.dll
Microsoft.VisualStudio.TestPlatform.Extensions.dll
Then in the Unit Test Project add a reference to the v10.1
Microsoft.VisualStudio.QualityTools.LoadTestFramework.dll

Creating instance of class accessor

I am currently writing a unit test framework which shall in the end run standard unit tests written in Visual Studio. The Framework is currently not working correctly with accessors. Consider the following test method:
[TestMethod()]
public void TestMethod()
{
ExampleMethods_Accessor target = null;
target = new ExampleMethods_Accessor();
target.SomeMethod();
}
In this example, the accessor has been generated by Visual Studio. The unit test works perfectly fine when run using the Unit Testing environment of Visual Studio. However, I would like to invoke the TestMethod() from within my Framework. At the line "target = new ExampleMethods_Accessor()", the following exception is thrown:
The type initializer for "Proband.ExampleMethods_Accessor" threw an excepition.
Inner exception:
Could not load file or assembly: Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null...
Has anyone an idea of how the Microsoft Unit Testing Framework invokes unit tests? I was thinking it might be due to the missing TestContext object. This is "null" in my case. When starting the unit test in Visual Studio, the TestContext object contains a lot of information. Could it be, that I need to initialize it properly? How would it need to be initialized?
Thanks for all help,
Christian
EDIT:
I kept experimenting with the way accessors are working. I used ILSpy to see what code is being generated into the Proband_Accessor.dll. It turns out that the instruction causing the exception is:
SomeClass_Accessor.m_privateType = new PrivateType("Probant, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Probant.SomeClass");
I modified my unit test code to be like this (just for test):
[TestMethod()]
[DeploymentItem("Proband.dll")]
public void SomeMethodTest()
{
ExampleMethods_Accessor target = null;
ExampleMethods c = null;
try
{
Assembly.Load("Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); // this works fine
PrivateType tx = new PrivateType(typeof(ExampleMethods)); // this works fine as well (also without loading the assembly)
PrivateType t = new PrivateType("Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Proband.ExampleMethods"); // this causes the exception
c = new ExampleMethods(); // this works fine
target = new ExampleMethods_Accessor(); // this causes the exception as well
}
catch (Exception ex)
{
Console.WriteLine();
}
int actual;
actual = target.SomeMethod();
}
I do absolutely not understand, why "new PrivateType("Proband, Version...." does not work. Has anyone an idea?
I have managed to create a workaround for the issue.
To my AppDomain, I am adding an AssemblyResolveEventHandler:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
This event handler contains the following code:
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
if(args.Name == "Proband, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
{
// resolving correct assembly of type under test
return typeof(ExampleMethods).Assembly;
}
else
{
return null;
}
}
Now the line of code "target = new ExampleMethods_Accessor();" works fine and returns the correct accessor object.
I still do not understand, why the Assembly cannot be resolved automatically.
Even if it is very unlikely that anyone will have the same problem: I hope this answer helps someone :)
I am not doing anything nearly as complex, but I had:
web application project using .NET 3.5
Configuration project using .NET 3.5
Test project using .NET 3.5
I was getting the same BadImageFormat exception when trying to run a unit test using an accessor.
I found the following link:
http://connect.microsoft.com/VisualStudio/feedback/details/677203/even-after-installing-vs2010-sp1-unit-tests-targeting-3-5-framework-fail-if-they-are-using-private-accessor#details
The second work-around solved my problem. I changed the test project to target .NET 4.0 and it worked.
I just had this exact problem, and it was because I removed the DeploymentItem attribute from the test method. Once I added it again, I no longer got the error on the build machine.
[TestMethod]
[DeploymentItem("FedImportServer.dll")] // ** This is necessary for the build machine. **
public void SourceFileStillExistsAfterProcessingFails()
Note: I never got the error when running it locally.
This is the error:
Test method FedImportTests.FedImportServiceHostTest.FileNoLongerExistsAfterSucessfulProcessing threw exception:
System.TypeInitializationException: The type initializer for 'FedImportServer.Processing.FileProcessor_Accessor' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'FedImportServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

Force MonoDevelop to 'Run Tests' under a specific runtime

A heap of our unit tests are failing under Mono on OS X with the following error:
System.TypeLoadException : Could not load type 'System.Func``2' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
On of the unit tests in question:
[Test]
public void CanAuthenticateValidUser()
{
const string testUsername = "jappleseed";
var repo = new Mock<IUserRepository>();
repo.Setup(x => x.GetByUsername(testUsername)).Returns(GetTestUser());
var authenticator = new Authenticator(repo.Object);
var result = authenticator.Authenticate(testUsername, "test");
Assert.That(result, Is.True);
}
Running against Mono 2.8, with MonoDevelop 2.4.
Anyone got any suggestions to get around this?
Edit:
Should point out this error is coming from the inbuilt "Run Tests" command in the "Unit Tests" pad in MonoDevelop.
Edit 2:
Forcing the runtime as per jpobst suggestion runs in the console. I guess the question has become how does one get MonoDevelop to exhibit run tests under a specific framework?
shimms:Debug shimms$ mono ~/Development/nunit/bin/net-2.0/nunit-console.exe Convergence.Core.Services.Tests.dll
Throws the same exceptions, however:
shimms:Debug shimms$ mono --runtime=v4.0.30319 ~/Development/nunit/bin/net-2.0/nunit-console.exe Convergence.Core.Services.Tests.dll
All tests pass
There isn't an assembly called "mscorelib", it's "mscorlib". Is that a typo? Or a broken reference?
Second try:
Are you sure your tests were compiled against 4.0 (dmcs)?
You can also try overriding the runtime with:
mono --runtime=v4.0.30319 mytests.exe

How do I pass references as method parameters across AppDomains?

I have been trying to get the following code to work(everything is defined in the same assembly) :
namespace SomeApp{
public class A : MarshalByRefObject
{
public byte[] GetSomeData() { // }
}
public class B : MarshalByRefObject
{
private A remoteObj;
public void SetA(A remoteObj)
{
this.remoteObj = remoteObj;
}
}
public class C
{
A someA = new A();
public void Init()
{
AppDomain domain = AppDomain.CreateDomain("ChildDomain");
string currentAssemblyPath = Assembly.GetExecutingAssembly().Location;
B remoteB = domain.domain.CreateInstanceFromAndUnwrap(currentAssemblyPath,"SomeApp.B") as B;
remoteB.SetA(someA); // this throws an ArgumentException "Object type cannot be converted to target type."
}
}
}
What I'm trying to do is pass a reference of an 'A' instance created in the first AppDomain to the child domain and have the child domain execute a method on the first domain. In some point on 'B' code I'm going to call 'remoteObj.GetSomeData()'. This has to be done because the 'byte[]' from 'GetSomeData' method must be 'calculated' on the first appdomain.
What should I do to avoid the exception, or what can I do to achieve the same result?
The actual root cause was your dll was getting loaded from different locations in the two different app domains. This causes .NET to think they are different assemblies which of course means the types are different (even though they have the same class name, namespace etc).
The reason Jeff's test failed when run through a unit test framework is because unit test frameworks generally create AppDomains with ShadowCopy set to "true". But your manually created AppDomain would default to ShadowCopy="false". This would cause the dlls to be loaded from different locations which leads to the nice "Object type cannot be converted to target type." error.
UPDATE: After further testing, it does seem to come down to the ApplicationBase being different between the two AppDomains. If they match, then the above scenario works. If they are different it doesn't (even though I've confirmed that the dll is loaded into both AppDomains from the same directory using windbg) Also, if I turn on ShadowCopy="true" in both of my AppDomains, then it fails with a different message: "System.InvalidCastException: Object must implement IConvertible".
UPDATE2: Further reading leads me to believe it is related to Load Contexts. When you use one of the "From" methods (Assembly.LoadFrom, or appDomain.CreateInstanceFromAndUnwrap), if the assembly is found in one of the normal load paths (the ApplicationBase or one of the probing paths) then is it loaded into the Default Load Context. If the assembly isn't found there, then it is loaded into the Load-From Context. So when both AppDomains have matching ApplicationBase's, then even though we use a "From" method, they are both loaded into their respective AppDomain's Default Load Context. But when the ApplicationBase's are different, then one AppDomain will have the assembly in its Default Load Context while the other has the assembly in it's Load-From Context.
I can duplicate the issue, and it seems to be related to TestDriven.net and/or xUnit.net. If I run C.Init() as a test method, I get the same error message. However, if I run C.Init() from a console application, I do not get the exception.
Are you seeing the same thing, running C.Init() from a unit test?
Edit: I'm also able to duplicate the issue using NUnit and TestDriven.net. I'm also able to duplicate the error using the NUnit runner instead of TestDriven.net. So the problem seems to be related to running this code through a testing framework, though I'm not sure why.
This is a comment to #RussellMcClure but as it is to complex for a comment I post this as an answer:
I am inside an ASP.NET application and turning off shadow-copy (which would also solve the problem) is not really an option, but I found the following solution:
AppDomainSetup adSetup = new AppDomainSetup();
if (AppDomain.CurrentDomain.SetupInformation.ShadowCopyFiles == "true")
{
var shadowCopyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (shadowCopyDir.Contains("assembly"))
shadowCopyDir = shadowCopyDir.Substring(0, shadowCopyDir.LastIndexOf("assembly"));
var privatePaths = new List<string>();
foreach (var dll in Directory.GetFiles(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath, "*.dll"))
{
var shadowPath = Directory.GetFiles(shadowCopyDir, Path.GetFileName(dll), SearchOption.AllDirectories).FirstOrDefault();
if (!String.IsNullOrWhiteSpace(shadowPath))
privatePaths.Add(Path.GetDirectoryName(shadowPath));
}
adSetup.ApplicationBase = shadowCopyDir;
adSetup.PrivateBinPath = String.Join(";", privatePaths);
}
else
{
adSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
adSetup.PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
}
This will use the shadow-copy directory of the main app-domain as the application-base and add all shadow-copied assemblies to the private path if shadow-copy is enabled.
If someone has a better way of doing this please tell me.

Categories