简体   繁体   English

Moq无法在构造函数中使用可为null的参数创建类的模拟对象

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

I have this class: 我有这门课:

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

I am trying to mock it using MOQ like this 我试图用这样的MOQ来模拟它

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. 无法实例化类的代理:TestClass。 Could not find a constructor that would match given arguments: System.Int32, System.String 找不到与给定参数匹配的构造函数: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. 如何使它识别第一个参数是Nullable System.Int32类型而不是System.Int32。

(Please ignore that I am mocking a class and not an interface.) (请忽略我正在嘲笑一个类,而不是一个接口。)

In order to Mock an object with Moq, the object itself must have a public empty constructor. 为了使用Moq模拟对象,对象本身必须具有 public空构造函数。 Methods you want to mock must be virtual in order to be overridden. 要模拟的方法必须是virtual的才能被覆盖。

Edit: 编辑:

I'm running Moq v4.0.20926 (latest from NuGet) and the following work: 我正在运行Moq v4.0.20926(来自NuGet的最新版本)以及以下工作:

[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";
    }
}

The reason for this is that boxing a nullable value doesn't really box the Nullable<T> value, it boxes the value inside. 这样做的原因是装入一个可以为空的值并没有真正包装Nullable<T>值,它将值放在里面。

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 如果框值的空值,你得到的值的盒装版本,这样的盒装版(int?)1相同的盒装版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. 换句话说,你的object[]数组根本没有获得可空值的副本,它只获取int值的副本或null -reference,它们都不带有Nullable<T>类型。

Here's some LINQPad code to test: 这是一些要测试的LINQPad代码:

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

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

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

Output: 输出:

1 1
System.Int32 System.Int32
null 空值
[NullReferenceException] [的NullReferenceException]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM