How do you mock an abstract class containing an internal abstract method using Moq?

I have class A , which I am a module for testing a method that takes class B as a parameter. Class B is what I'm trying to make fun of, and it is an abstract class. The class is similar to below.

 public abstract class B { internal abstract void DoSomething(); } 

My unit test looks like.

 [TestMethod] public void ClassA_Add_TestSomething() { var classA = new A(); var mock = new Mock<B>(); classA.Add(mock.Object); // Assertion } 

I get the following exception.

TestSomething's testing method threw an exception:
System.ArgumentException: Type to mock must be an interface or an abstract or non-printable class. ---> System.TypeLoadException: the "DoSomething" method in the type "Castle.Proxies.BProxy" from the assembly "DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null" has no implementation.

I can get around this by making the method virtual rather than abstract, but this is not what I want to accomplish with the design of the API. I also tried to provide it with an implementation via mock.Setup(m => m.DoSomething()) no avail. Is this possible with Moq, or will I have to create a specific test class that derives from the abstract class B? I wanted to avoid creating specific types, which lesions might some of the taunts or falsifications use, or am I mistaken here?

Change I found that if I create a public abstract method, this problem does not occur. Therefore, I assume that the real question is that this is possible even when using the internal method when using InternalsVisibleTo and Moq.

+5
source share
2 answers

Think about why you have an internal abstract method for an open class. Others will not be able to implement the abstract method because they are not visible to them. Perhaps this is what you want. Sometimes, given various design constraints, this is a valid approach. If your library will be consumed by others, I would recommend at least building internal constructors, so no one understands that they can implement an abstract class.

+3
source

Moq relies on Castle Dynamic Proxy to implement its layouts. At run time, a new assembly is created and loaded into your AppDomain by Moq (name DynamicProxyGenAssembly2, which appears in the exception message).

The problem is that this assembly cannot access the inner classes and members of your own code , because they are not visible outside the assembly where you declared them.

A workaround is to tag your assembly with InternalsVisibleToAttribute and specify the name of the dynamically generated assembly:

 [InternalsVisibleTo("DynamicProxyGenAssembly2")] 

Remember, however, that this solution is based on implementation details and may not work in future versions.

+5
source

Source: https://habr.com/ru/post/1204021/


All Articles