Moq cannot create mock object of class with nullable parameter in the constructor

回眸只為那壹抹淺笑 提交于 2019-12-07 01:00:54

问题


I have this class:

public class TestClass
{
 public TestClass(int? foo, string bar)
 {
   //..Something
 }
}

I am trying to mock it using MOQ like this

var mockA = new Mock<A>(new object[] {(int?)1, string.Empty})

or this,

var mockA = new Mock<A>(new object[] {1 as int?, string.Empty})

even this

var mockA = new Mock<A>(new object[] {(int?)null, string.Empty})

When I try to get the object like this

var objA = mockA.Object

it throws this exception

Can not instantiate proxy of class: TestClass. Could not find a constructor that would match given arguments: System.Int32, System.String

(for the third one it throws null reference exception)

How to make it recognize that first argument is of type Nullable System.Int32 and not System.Int32.

(Please ignore that I am mocking a class and not an interface.)


回答1:


In order to Mock an object with Moq, the object itself must have a public empty constructor. Methods you want to mock must be virtual in order to be overridden.

Edit:

I'm running Moq v4.0.20926 (latest from NuGet) and the following work:

[TestMethod]
public void TestMethod1()
{
    var mock = new Mock<TestClass>(new object[] {null, null});
    mock.Setup(m => m.MockThis()).Returns("foo");

    Assert.AreEqual("foo", mock.Object.MockThis());
}

public class TestClass
{
    public TestClass(int? foo, string bar)
    {
    }

    public virtual string MockThis()
    {
        return "bar";
    }
}



回答2:


The reason for this is that boxing a nullable value doesn't really box the Nullable<T> value, it boxes the value inside.

Basically:

  1. If you box a nullable value that has a value, you get a boxed version of the value, so a boxed version of (int?)1 is the same as a boxed version of 1
  2. If you box a nullable value that does not have a value, you get a null-reference, which has no type

You can think of the boxing operation as similar to this:

public static object Box(int? value)
{
    if (value.HasValue)
        return value.Value; // boxes the int value

    return null;            // has no type
}

In other words, your object[] array doesn't get a copy of the nullable value at all, it just gets a copy of the int value, or a null-reference, neither of which carries the Nullable<T> type.

Here's some LINQPad code to test:

void Main()
{
    int? i = 1;
    object o = i;

    o.Dump();
    o.GetType().Dump();

    i = null;
    o = i;
    o.Dump();
    o.GetType().Dump();
}

Output:

1
System.Int32
null
[NullReferenceException]



来源:https://stackoverflow.com/questions/6378223/moq-cannot-create-mock-object-of-class-with-nullable-parameter-in-the-constructo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!