Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock a class having no default construtor

Tags:

c#

moq

nunit

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.

like image 333
komal Thawani Avatar asked Sep 17 '25 23:09

komal Thawani


1 Answers

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.

like image 168
TheFastCat Avatar answered Sep 19 '25 14:09

TheFastCat