Banging my head against a wall trying to get a really simple testing scenario working.
I'm sure I'm missing something really simple!
Whatever I do, I seem to get the following error from the NUnit gui when running a test against my DLL:
System.TypeLoadException : Type 'Castle.Proxies.ITestProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is attempting to implement an inaccessible interface.
Now I've seen reference to this error in heaps of places when looking in Stack Overflow and elsewhere, but the solution I keep finding doesn't seem to help. And I'm not even using an internal interface at this stage! The solution I see around the place is too put the following line in AssemblyInfo.cs
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
I'm using:
Visual Studio 2010 Professional
c# 4.0
Moq 4.10810.8 Beta (bin deployed)
NUnit 2.5.5 (Installed in GAC)
To recreate this error, all I need to do is:
Create a new class library project
Reference Moq and Unit (as above)
Create an interface. I've called my interface ITest, made it public, and it has one method which is 'string TestMethod();'. Am doing this in the local project for simplicity.
Create a class called 'Testing', decorated with [TextFixture] and a test method called 'TestMethod' decorated with [Test]
Build the project, then run NUnit against the resulting dll in the Debug folder.
Here's the contents of my test class
namespace MoqTest {
[TestFixture]
public class Testing {
[Test]
public void TestMethod() {
var testMock = new Mock<ITest>();
testMock.Setup(x => x.TestMethod()).Returns("String val");
var xyz = testMock.Object;
Assert.AreEqual(1, 1);
}
}
}
---- UPDATE ---
After changing Moq version from 4.10810.8 to 4.0.10501.6 everything works fine!
The following test passes for me:
public interface ITest { string TestMethod(); }
public class Testing
{
[Test]
public void TestMethod()
{
var testMock = new Mock<ITest>();
testMock.Setup(x => x.TestMethod()).Returns("String val");
var xyz = testMock.Object;
Assert.AreEqual(1, 1);
}
}
If your interface is public and in the same assembly, there really should be no problem. I suspect that you just missed an accessibility keyword somewhere, as a non-public interface does provoke a runtime error because the proxying assembly will be unable to instantiate a type based on it.
Probably the best thing to do is start with the code I've provided and change one thing at a time until it matches your failing code. If you run your test in between each change, I presume you'll find what was missing.
If you do go back to an internal interface, note that your InternalsVisibleTo statement must be in the same assembly as your internal interface, not your test assembly. Also note that if your assembly is strongly named you may need to add a public key fingerprint to your InternalsVisibleTo statement as described in MSDN.
Yeah I had the same issue with Moq.4.0.10810.8 for NET40... When I downgraded to version 4.0.10531.7 everything went green again!
I'm using 4.10.1 now, and I got this same issue. I tried downgrading to 4.10.0, but to no avail.
I finally found that, although the interface I was using was marked as public, it was in a class without a modifier. I found 2 things got it to work:
1) Pull the interface outside of the class. Because the class was no longer making the interface internal, it became accessible to the assembly.
2) Mark the class public. With all parts of the path to the interface being marked public, the assembly had no trouble accessing.
These strategies worked in both 4.10.0 and 4.10.1.
Related
I am trying to refactor a code base. This requires moving types to different assemblies to fix some dependency issues. I want to avoid requiring my customers to recompile as a result of these changes. I've noticed that interfaces that are explicitly implemented and declare events do not forward correctly. For example:
Foo.dll defines:
public interface IFooInterface
{
void Foo();
event EventHandler FooEvent;
}
My customer's FooProgram.exe depends on Foo.dll and defines:
public class Foo : IFooInterface
{
event EventHandler IFooInterface.FooEvent
{
add { }
remove { }
}
void IFooInterface.Foo() { }
}
Now I move the type. I create a new assembly NewFoo.dll. I move IFooInterface from the old assembly to the new assembly and put it under the same namespace. Foo.csproj takes a project reference to NewFoo.csproj and I add the forwarding attribute:
[assembly: TypeForwardedTo(typeof(IFooInterface))]
I place Foo.dll and NewFoo.dll in the bin directory for Foo.exe and Foo.exe errors with:
Unhandled Exception: System.TypeLoadException: Method 'add_FooEvent' in type 'FooProgram.Foo' from assembly 'FooProgram, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at FooProgram.Program.Main(String[] args)
Why does this happen? If I implicitly implement the interface on Foo it works, but that doesn't do me any good as it means anyone who wrote vb.net code against my library will break. What other constructs have this problem with Type Fowrarding? Is there a way to get the behavior I want?
It looks like this is a bug in the old version of .NET Framework we're using (4.5). I upgraded to 4.8 and it works as expected. I found this blog post by Rick Strahl that describes how TypeForwardTo is what makes .NET Standard capable of resolving to the correct targets. This made me realize it must work for all types on a more modern version of the framework.
I recently encountered an odd issue when performing unit tests. My solution contains a helper class with a property for getting the directory of the executing assembly. It looks like this:
public static class DirectoryHelper
{
public static string ExecutingAssemblyDirectory
{
get
{
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
var path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
}
This method is called through various test classes to get relative file paths to dependent resources.
Take the following contrived projects as examples:
TestProject1.dll - TestFixture1.cs
[TestFixture]
public class TestFixture1
{
[Test]
public void VerifyExecutingAssemblyDirectory1()
{
StringAssert.Contains(#"\TestProject1\bin\Debug",
DirectoryHelper.ExecutingAssemblyDirectory);
}
}
TestProject2.dll - TestFixture2.cs
[TestFixture]
public class TestFixture2
{
[Test]
public void VerifyExecutingAssemblyDirectory1()
{
StringAssert.Contains(#"TestProject2\bin\Debug",
DirectoryHelper.ExecutingAssemblyDirectory);
}
}
When these tests are ran individually they pass and the location of the returned assembly is the debug folder of the test class.
However, when ran together, TestFixture2.VerifyExecutingAssemblyDirectory2() is actually returning the path to the bin folder of TestProject1, rather than TestProject2.
I'm trying to determine why this behavior is happening and understand a better way of going about this.
I've found that using .GetCallingAssembly will resolve this problem, but it doesn't seem like I should have to do this.
I've created an example to reproduce this issue and posted to GitHub. TylerNielsen/NUnitExecutingAssemblyExample
Note: I'm aware of the TestContext.TestDirectory in NUnit, however this library is currently not dependent on NUnit and I'd prefer to keep it that way.
UPDATE
I'm running the NUnit tests through both Resharper in Visual Studio and via NUnit3-Console. When I run using NUnit3-Console, I'm only specifying the two individual .dlls and not providing any other arguments.
Both TestProject1 and TestProject2 reference the assembly containing DirectoryHelper. I'm assuming that your references cause the assembly to be copied to the individual (separate) output directories.
When you run both test assemblies together, one of them causes it's "personal" copy of that assembly to be loaded. The second one finds that the assembly is already in memory.
Of course, this behavior will depend on how you run the assemblies, which you haven't said. In the case where you use nunit3-console, it will also depend on your command-line arguments, especially whether you use a separate process for each assembly.
I want to add a custom test reporter to NUnit. I already did it with NUnit2, but I now need to use NUnit3.
To implement the reporter, I need to get various events from the framework, like start, end and failure of tests.
In NUnit2 I used NUnitHook to register my EventListener and it worked pretty good.
In NUnit3 I need to use the extension point mechanism, but when I add the extension point to the project, VisualStudio (2012 ultimate) immediately fails to discover the NUnit tests.
[TypeExtensionPoint(Description = "Test Reporter Extension")]
public class MyTestEventListener : ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
If I remove the ITestEventListener implementation declaration from the class, it rediscovers the tests perfectly.
[TypeExtensionPoint(Description = "Test Reporter Extension")]
public class MyTestEventListener //: ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
Am I doing something wrong? is there a better way to achieve it?
You don't say where you are putting this code, but I am suspecting it's in your test assembly. If so, that's not where it belongs. NUnit engine extensions get installed into the NUnit engine, so they need to be in a separate assembly. Once you have a separate assembly, you need to tell the engine where it is. Currently, you do this by creating a file of type .addins in the same directory as the engine. (You could modify the existing file, but that introduces maintenance problems in the future)
A future release will have an easier way to install addins, but they will continue to be entirely separate from your tests.
A further problem is that you are using TypeExtensionPointAttribute. I didn't notice this originally in your code and it's probably the biggest error so I'm adding this info now.
An "ExtensionPoint" is the thing you are extending. NUnit defines ExtensionPoints, while you create Extenisons to extend them. TypeExtensionPointAttribute is used inside NUnit to define extension points. It's not used by you. You use the ExtensionAttribute to define your extension.
Your extension should be defined something like this:
[Extension(Description = "Test Reporter Extension", EngineVersion="3.4")]
public class MyTestEventListener : ITestEventListener
{
public void OnTestEvent(string report)
{
Console.WriteLine(report);
}
}
You don't say what version of NUnit you are running. Test Listeners are only supported beginning with version 3.4. The EngineVersion property above is purely documentary at this point, because 3.4 is also the first version to recognize it.
There is a new writeup in the NUnit docs that may be helpful: https://github.com/nunit/docs/wiki/Writing-Engine-Extensions
I've got a test class that looks like:
// disclaimer: some type names have been changed to protect IP,
// there may be inconsistencies
using Moq;
using MyComp.MyProj.DataAccessLayer;
namespace Test.Common.Data.DataAccessLayer
{
public class Test
{
Mock<IApplicationData> appData;
Mock<IConfig> config;
public Test()
{
this.appData = new Mock<IApplicationData>();
this.config = new Mock<IConfig>();
}
[Fact]
public void GetNewInstance_WithoutUser( )
{
this.config.Setup(c => c.GetConfigInt(It.IsAny<string>())).Returns(1);
// DalFactory is a type in MyComp.MyProj.DataAccessLayer
var dal = DalFactory.GetDataAccessLayer(1, "fakestring", (IApplicationData)this.appData.Object, (IConfig)this.config.Object);
Assert.IsType <IDataAccessLayer>(dal);
}
}
}
```
The problem here is that whenever it tries to access the DalFactory type, it throws this exception:
System.TypeLoadException : Could not load type 'MyComp.MyProj.DataAccessLayer.DalFactory' from assembly 'DataAccessLayer, Version=0.9.0.0, Culture=neutral, PublicKeyToken=null'.
The Version is the key there, since the MyComp.MyProj.DataAccessLayer is in an assembly with Version 8.0.x while the test is in an assembly with Version 0.9.0 (or 1.0.0 or 0.0.1, I've tried several values).
Question is, why would Moq be trying to load the wrong assembly for this type?
I've tried: looking in the GAC to see if there's an assembly being loaded from there, re-adding the project references, changing AssemblyTitle in the test AssemblyInfo.cs, changing the name of the class the test is in and using an alias on the using statement. No effect.
The method for GetDataAccessLayer is a public static so I don't think InternalsVisibleTo factors in here. If I F12 navigate to the type being tested, it goes fine, gets to the right place.
If I put Assert.True(1 == 1); as the only thing in the Test method, it runs fine and passes.
What should I try next to fix this issue?
Try:
re-build your code in MyComp.MyProj.DataAccessLayer project
re-build Test project
run tests again
see if that helps
Also make sure the client Target Framework is the same for both projects (Properties > Application > Target Framework)
So here is my issue. I have a complex archetecture of interfaces and abstract classes that I am trying to load up via Assembly.LoadFrom("x.dll"). When certain types that have an interface implementation where the implementation is explicit in a base class are trying to be loaded, I am getting a TypeLoadException saying:
Method 'MyMethod' in type 'MyPart2DerivedType' from assembly 'MyPart2Assembly, version...' does not have an implementation. I am trying to understand why this is as I have gone through several articles and have even attempted to delete the obj files and dlls manually. Here are the references to what I have done so far:
Solution to TypeLoadException
TypeLoadException says 'no implementation', but it is implemented
Visual Studio Forumns: TypeLoadException
Private accessors and explicit interface implementation
So here is my example code:
//This is in project 1
public interface IFooPart1
{
void DoStuff();
}
//This is in project 2
public interface IFooPart2
{
void DoOtherStuff();
}
//This is in project 3
public interface IFooPart3: IFooPart1, IFooPart2
{
void DoEvenMoreStuff();
}
//This is in project 4
public abstract class MyBaseType: IFooPart1, IFooPart2
{
void IFooPart1.DoStuff()
{
DoStuffInternal();
}
void IFooPart2.DoOtherStuff()
{
DoOtherStuffInternal();
}
}
//This is in project 5
public class MyDerivedType: MyBaseType, IFooPart3
{
public void DoEvenMoreStuff()
{
//Logic here...
}
}
//Only has references to projects 1, 2, & 3 (only interfaces)
public class Program
{
void Main(params string[] args)
{
//Get the path to the actual dll
string assemblyDll = args[0];
//Gets the class name to load (full name, eg: MyNameSpace.MyDerivedType)
string classNameToLoad = args[1];
//This part works...
var fooAssembly = Assembly.LoadFrom(assemblyDll);
//Here we throw a TypeLoadException stating
// Method 'DoStuff' in type 'MyDerivedType' from assembly 'Project 5...' does
// not have an implementation.
Type myDerivedTypeExpected = Assembly.GetType(classNameToLoad);
}
}
Note: If I move the explicit implementation to MyDerivedType instead of MyBaseType it works... but I don't get why I would have to do that. Seems like I should be able to. This code is only an example, the actual code has a factory that returns the loaded class but only via the interface type. (eg: var myDerivedType = GetInstance();)
Okay for everyone that is interested in my stupid fix. Here was my problem:
Project6 (which was the console app) has PROJECT references to the other projects, not references to the dlls in the location that they are supposed to build to. The other projects actually were being built to a specific repository area. So, the console application was using it's own version of the dll's when it was trying to automatically load the dependancies. This evidently made some other type way down there that was being dynamically loaded to not be loaded because it was not in the same folder as the dlls that were there...
So in short, Assembly.LoadFrom might cause you to load an assembly twice, but .NET treats it like a different assembly!!! This may introduce some real odd errors when trying to dynamically load types!!!
Please learn from my frustration/mistake. Fiends don't let freinds DI alone (code review is key to catching this stupid stuff).
I've had a similar problem caused by one of my projects having a reference to an older version of a nuget package dependency. The older version didn't have an implementation for one of the methods.