How to mock a class without default constructor us

2019-09-04 09:37发布

问题:

Using Moq, I need to create a fake over an existing class (not interface*) that has no default ctor.

I can do this using the "traditional" syntax:

var fakeResponsePacket = new Mock<DataResponse>(
    new object[]{0, 0, 0, new byte[0]}); //specify ctor arguments

fakeResponsePacket.Setup(p => p.DataLength).Returns(5);

var checkResult = sut.Check(fakeResponsePacket.Object);

My question is: Is there a way to do the same using the newer Mock.Of<T>() syntax ?

From what I can see, there are only two overloads for Mock.Of<T>, none of which accept arguments:

//1 no params at all
var fakeResponsePacket = Mock.Of<DataResponse>(/*??*/);
fakeResponsePacket.DataLength = 5;

//2 the touted 'linq to Moq'
var fakeResponsePacket = Mock.Of<DataResponse>(/*??*/
    p => p.DataLength == 5
);

var checkResult = sut.Check(fakeResponsePacket);

--
* I wanted to use an interface. But then reality happened. Let's not go into it.

回答1:

No, there appears to be no way of doing that.

Side-remark: In the "old" syntax, you can just write:

new Mock<DataResponse>(0, 0, 0, new byte[0]) //specify ctor arguments

since the array parameter there is params (a parameter array).

To get around the issue with 0 being converted to a MockBehavior (see comments and crossed out text above), you could either do:

new Mock<DataResponse>(MockBehavior.Loose, 0, 0, 0, new byte[0]) //specify ctor arguments

or do:

var v = 0; // this v cannot be const!
// ...
new Mock<DataResponse>(v, 0, 0, new byte[0]) //specify ctor arguments

but this is not really part of what you ask, of course.