komal Thawani
komal Thawani

Reputation: 139

How to Mock a class having no default construtor

I want to mock a class having no default constructor and call a method inside it. This method calls another method of the same class. I want to setup this second method to return a value ad execute rest of the part of first method to test some results.

[Test]
public void TestFunction(){
    int d=0;
    var mockObject = new Mock<Foo>(){MockBehaviour.Default, p, q}; //p and q are parameters for Foo constructor
    mockObject.Setup(x=>x.func2(a,b,c)).Returns(d);
    mockobject.Object.func1();
}


Class Foo{
    public Foo(int x,int y){}

    public virtual int func1(){
       DoSomething;
       func2();
    }

    public virtual int func2(){}
}

I am mocking Foo because I don't want func2() to be executed when I test func1(). Hence I setup the mockObject to return a value for func2() without executing it when func1() calls func2().

When I run this test case I get exception "System.NotSupportedException : Parent does not have a default constructor. The default constructor must be explicitly defined."

If I see the mockObject while debugging the test case, mockObject.Object is not getting initialized. I am new to unit testing and Mock. Can someone help me about where I am going wrong.

Upvotes: 4

Views: 5548

Answers (2)

TheFastCat
TheFastCat

Reputation: 3474

The answer to your actual question:

How to Mock a class having no default construtor

You need to use a different overload of the Mock ctor so that arguments are passed to the non-default Foo ctor:

  var mockObject = new Mock<Foo>(1, 2);

However your testing strategy is flawed and I believe this is due to how you understand Moq to function.

Mocks are useful for trivializing complex dependencies of what you are testing - instead of instantiating, handling their lifecycles, you mock them. This is okay when they don't affect the code you are actively testing (as others have mentioned in this question) -- that is not your intent here. Since Func2() is tightly coupled to the implementation of func1(), the way that the code is written now, there is not a way to execute Func1() without executing Func2().

You could change the function signature of Func1() to take Func2() as an argument -- this would allow you to modify which function is passed to it during testing (and allow you to Mock the behavior of Func2() easily. However you've already said this is an impossibility.

Upvotes: 3

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37050

Too answer your question being posted you may simply provide the arguments, as suggested in this thread:

var mockObject = new Mock<Foo>(MockBehaviour.Default, FooParameters);
mockObject.Setup(x=>x.func2(a,b,c)).Returns(d);
mockobject.Object.func1();

However this isn´t a good idea though. Usually you shouldn´t mock your system under test. Doing so may indicate that your class is doing too much and needs to be restructured, in order to do exactly one single thing.

However there may be situations where a class has several API-members that depend on each other. Think of an overload-chain where you want to test multiple overloads. Of course it´s easy to write a test for the most inner overload (with most params). However if want to test if your other overloads set the params for the most inner one correctly, you´re indeed stuck.

void DoSomething()
{
    var param = ...
    DoSomething(param);
}
void DoSomething(int p)
{
    // the most inner overload
}

There isn´t a general rule how to solve that dependency. I tend do subclass my system-under test in those cases and override its (virtual) members with an empty body - which is what MOQ internally does also.

Upvotes: 2

Related Questions