Moq cannot create class mock object with nullable parameter in constructor

I have this class:

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

I am trying to mock this with an MOQ like this

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

or that,

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

even this one

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

When I try to get an object like this

 var objA = mockA.Object 

he throws this exception

Unable to instantiate class: TestClass. Could not find a constructor that matches the given arguments: System.Int32, System.String

(for the third, it throws a null reference exception)

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

(Please ignore that I am mocking the class, not the interface.)

+6
source share
2 answers

To compose an object using Moq, the object itself must have a public empty constructor. The methods you want to make fun of must be virtual so that you can override them.

Edit:

I run Moq v4.0.20926 (the last of 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"; } } 
+7
source

The reason for this is that a box with a null value does not really put a Nullable<T> value, it puts a value inside.

Basically:

  • If you set a value with a null value of value, you get a boxed version of the value, so in the box, version (int?)1 is the same as in box of version 1
  • If you set a value with a null value that does not matter, you will get a null reference that is not of type

You can come up with a boxing operation 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 does not receive a copy of the NULL value at all, it just receives a copy of the int or null reference value, none of which carry a Nullable<T> .

Here are some LINQPad for testing:

 void Main() { int? i = 1; object o = i; o.Dump(); o.GetType().Dump(); i = null; o = i; o.Dump(); o.GetType().Dump(); } 

Conclusion:

1
System.Int32
zero
[NullReferenceException]

+4
source

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


All Articles