Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have class A that I am unit testing a method on that takes class B as a parameter. Class B is what I am trying to mock out, 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 receive the following exception.

Test method TestSomething threw exception:
System.ArgumentException: Type to mock must be an interface or an abstract or non-sealed class. ---> System.TypeLoadException: Method 'DoSomething' in type 'Castle.Proxies.BProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.

I can get around this by making the method virtual instead of abstract, but that is not what I want to accomplish with the API design. I have also tried providing it a implementation through mock.Setup(m => m.DoSomething()) to no avail. Is this possible with Moq, or am I going to have to create a concrete test class that derives from the abstract class B? I wanted to avoid creating concrete types, which kind of defeats some of the purpose of using a mocking or stubbing framework, or am I mislead here?

Edit I have discovered that if I make the method public abstract this issue does not occur. So I guess the real question is if this is even possible with an internal method when using InternalsVisibleTo and Moq.

like image 254
David Anderson Avatar asked Oct 04 '14 20:10

David Anderson


People also ask

What can be mocked with MOQ?

Moq can be used to mock both classes and interfaces.

Can we create a mock for abstract class?

mock() method for mocking the abstract classes. Using PowerMock instead of Mockito. mock() is a better approach as it can have control over the private as well as static methods. Step1: Create an abstract class named Abstract_class that contains both abstract and non-abstract methods.

Can abstract class be internal?

An Abstract class can have access modifiers like private, protected, and internal with class members. But abstract members cannot have a private access modifier. An Abstract class can have instance variables (like constants and fields). An abstract class can have constructors and destructors.

What is MOQ mocking framework?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.


1 Answers

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

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

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

[InternalsVisibleTo("DynamicProxyGenAssembly2")]

Remember however that this solution relies on an implementation detail, and might stop working in future versions.

like image 172
Gabriel Boya Avatar answered Sep 22 '22 10:09

Gabriel Boya