happygilmore
happygilmore

Reputation: 3105

Implementing mocking objects with Moq when constructor has parameters

I have read this answer by Ragzitsu for the same question. I am still confused how to implement things though. Can somebody give me an example of an implementation.

I have the following classes:

class Fizz : IFizz
{
}

class Buzz : IBuzz
{

}

class Bar : IBar
{

}

class Foo : IFoo
{
    public Foo(IBar bar, IFizz fizz, IBuzz buzz)
    {
        //initialize etc.
    }

    //public methods
}

What is the practical way to get around the constructor here? I want to do something like

var foo = new Mock<IFoo>();

In other words how would the code look after the advice

The best thing to do would be right click on your class and choose Extract interface.

Upvotes: 37

Views: 93635

Answers (7)

Josh Gust
Josh Gust

Reputation: 4445

TL;DR

It's unclear what you're really trying to do.

If you have already defined the interface IFoo (which is what your question seems to show) and you need to mock it to another type, you're already set: var bazz = new Bazz(new Mock<IFoo>());

If you have a concrete class Foo that you haven't abstracted into an interface that you need to provide to another type as a dependency, then extracting an interface is one of the more common ways to allow the initialization of a Bazz object without creating an actual Foo class. Depending on what you're actual code looks like, you might limit scope by abstracting into IFoo only the parts of Foo that Bazz depends on. The other way is to mock the concrete and provide moq with the constructor arguments to use. You'll need to make sure that the dependency parts of Foo are "Mock-able" (public virtual) in order to provide the Mock with your setup and results.

Read More:

To answer the question of

how would the code look after the advice The best thing to do would be to ... Extract interface?

the advice to extract an interface may not be exactly what you're looking for. As it was mentioned in other answers, we are not sure what it is you are actually trying to test.

If you are trying to test functionality on the concrete Foo implementation of IFoo then extracting an interface and mocking IFoo isn't really going to help you, because moq is going to implement the interface itself and only provide the "functionality" you tell it to provide in the setup methods and properties on that implementation. If this is what you are doing, AND the method under test calls some other method on the concrete Foo implementation, AND that method is something you want to provide an abstraction for, then I would do as @Chris Marisic mentioned and change the method you desire to abstract to virtual. With this as virtual you can use a mocking framework to provide the abstraction, or do as I have done in the past and create a sub type off the subject under test in the test class.

public class MyFooTests
{
    ... // Tests
    private class SubFoo : Foo
    {
        public override void MethodToAbstract(bool par)
        {
            // do something expected
        }
    }
}

With this method you are still going to need to provide something to the constructor of Foo, but that would be a prime case for using mocks on those interfaces.

Now, if you are testing Foo and the method under test is just calling methods on IBar, IFizz, IBuzz, and there is no other abstraction you want to create, then you're already setup. Mock those interfaces, set them up to return what you expect in a particular test case, and provide Foo with the mock objects.

The extract interface advice is really useful when your subject under test is dependent upon Foo, as mentioned by @Chris Marisic. However, I may not share his sentiment for not wanting to create interfaces in this situation. It depends on what smells more to you: creating an interface to provide mock-ability, or changing the modifier to provide the same. If you're going to change the modifier and still use moq to mock the concrete Foo, you will need to either expose a default constructor (pretty smelly to me) or create the mock with the given constructor arguments specification, as mentioned in your referenced answer.

Lets say you have the following:

public class Baz
{
    private Foo foo;

    public Baz(Foo inputFoo)
    {
        this.foo = inputFoo;
    }

    public bool GetFromTheFoo()
    {
        // other stuff here
        var fooStuff = this.foo.GetStuff();
        // logic on the stuff;
        return fooStuff != null;
    }
}

In the above Baz is dependent on Foo. After extracting an interface of Foo, Baz would need to accept IFoo.

Then Foo would look like it does in your question and IFoo would have a signature definition for the method you want to abstract away from Baz.

object GetStuff();

Now, in your test you would still use var foo = new Mock<IFoo>(); and give foo to your Baz test subject. Don't forget to setup the IFoo.GetStuff() method.

foo.Setup(f => f.GetStuff()).Returns(new object());

Because you have now created the IFoo abstraction there is no need to

get around the constructor here?

because the mock of IFoo only has a default constructor provided by moq.

Tangent

I personally prefer the interface approach, when it applies, because it removes indirect dependencies when testing. Let's say you have a class Baz that depends on Foo (not abstracted), but now Foo has dependencies on Fizz (or IFizz like in your question) in its constructor.

class Fizz 
{
}

class Foo // not abstracted : IFoo
{
    private Fizz fizz;
    public Foo(Fizz fizz)
    {
        this.fizz = fizz;
    }

    public object GetStuff()
    {
        return this.fizz;
    }
}

class Baz
{
  private Foo foo;

  public Baz(Foo inputFoo)
  {
    this.foo = inputFoo;
  }

  public bool GetFromTheFoo()
  {
    // other stuff here
    var fooStuff = this.foo.GetStuff();
    // logic on the stuff;
    return fooStuff != null;
  }
}

Testing Baz without an abstraction between Baz and Foo, would need to mock, stub, or create an actual Fizz to get a testable instance of Foo that we can give to the subject under test Baz.

public void TestBaz()
{
  var foo = new Foo(new Fizz());
  var baz = new baz(foo);

  var isFromBaz = baz.GetFromTheFoo();
}

Providing a controllable Fizz may not always be easy, and can make your tests explode with complexity that may not be related to Baz at all. But, if we have an IFoo between Foo and Baz, then the indirect dependency Fizz is removed because the ctor is an implementation detail, just like the actual functionality of IFoo.GetStuff.

class Baz
{
  private IFoo foo;

  public Baz(IFoo inputFoo)
  {
    this.foo = inputFoo;
  }

  public bool GetFromTheFoo()
  {
    // other stuff here
    var fooStuff = this.foo.GetStuff();
    // logic on the stuff;
    return fooStuff != null;
  }
}

Then out test can just be:

public void TestBaz()
{
  var foo = Mock.Of<IFoo>();
  var baz = new baz(foo);

  var isFromBaz = baz.GetFromTheFoo();
}

Some of this depends how you define a Unit that should be included in any given test. I try my best to make non-private methods the definition of a unit that needs testing, and if I can draw an abstracted-dependency line between one non-private making a call to another non-private, I do.

Upvotes: 10

Ashraf Alam
Ashraf Alam

Reputation: 3650

You can create mock where constructor has param arguments, by referring MockBehavior, shown below

Mock<testClass>(MockBehavior.Strict, new object[] {"Hello"}); 

Upvotes: 47

Chris Marisic
Chris Marisic

Reputation: 33128

The best thing to do would be right click on your class and choose Extract interface.

I'm going to address this concept in an orthogonal sense. I disagree with this statement, an interface is not the solution to the situtation in question.

Going back to the previous question's text:

public class CustomerSyncEngine {
    public CustomerSyncEngine(ILoggingProvider loggingProvider, 
                              ICrmProvider crmProvider, 
                              ICacheProvider cacheProvider) { ... }

    public void MethodWithDependencies() {
        loggingProvider.Log();
        crmProvider.Crm();
        cacheProvider.Cache();
    }
}

Note the method I added.

I believe the real question is when you are not specifically testing CustomerSyncEngine but instead are testing a class that depends on CustomerSyncEngine. Let's call this class SuperSyncEngine. Creating a test against SuperSyncEngine is going to be a pain since you have to mock out the entire CustomerSyncEngine with its 3 interfaces, along with any other additional dependencies SuperSyncEngine has.

Given that the code you are seeking to test is SuperSyncEngine that depends on CustomerSyncEngine an interface isn't the answer here. You could create ICustomerSyncEngine but that interface shouldn't be created merely for a mocking framework. The better solution is to change CustomerSyncEngine.MethodWithDependencies to be virtual

public virtual void MethodWithDependencies() {
    loggingProvider.Log();
    crmProvider.Crm();
    cacheProvider.Cache();
}

This would allow you to replace the method with a mocking framework ignoring the dependencies that CustomerSyncEngine comes with.

If you follow this approach you will likely need a default constructor exposed on CustomerSyncEngine to allow it to be mocked. It's possible you could work around that and satisfy the dependencies with null or some other values but that would be additional work when the goal is to reduce friction.

Upvotes: 8

therealjumbo
therealjumbo

Reputation: 1189

This is kind of an old post but I just ran into a similar problem (starting out with Moq). In case anyone else has a similar problem, here is what I had:

class Bar : IBar
{
}

class Foo : IFoo
{
    public Foo(IBar bar)
    {
        //initialize etc.
    }

    //public methods
}

class Manager : IManager
{
    public Manager(Foo foo)
    {
        //initialize etc
    }
}

What I'm trying to do is test Manager not Foo.

Here was my initial test code that threw an Error.

[TestFixture]
public class ManagerTest
{
    [Test]
    public void SomeTest()
    {
        var fooMock = Mock<IFoo>();
        var managerUnderTest = new Manager(fooMock.Object);
    }
}

The error is Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: Something.Models.Foo. Could not find a parameterless constructor.

Reading the Error message, Moq doesn't understand how to instantiate Foo, since there is no parameterless constructor, and we don't tell Moq how to instantiate one with parameters. Change that second section to:

[TestFixture]
public class ManagerTest
{
    [Test]
    public void SomeTest()
    {
        var barMock = Mock<IBar>();
        var fooMock = Mock<IFoo>(barMock.Object);
        var managerUnderTest = new Manager(fooMock.Object);

        //proceed with test
    }
}

Upvotes: 5

Oscar Bralo
Oscar Bralo

Reputation: 1907

If you go to tests your FOo class, you don´t need to mock. You only need to mock those classes which depends of the class that you are trying to tests.

Something like:

Mock<IBar> bar = new Mock<IBar>();
Mock<IBuzz> buzz = new Mock<IBuzz>();
Mock<IFizz> fizz= new Mock<IFizz>();

Foo foo = new Foo(bar.Object, buzz.Object, fizz.Object);

Then call the method in foo that you want to test ;)

If the method in foo uses some method inside bar/fuzz or fizz, then you should use the sintax like:

buzz.Setup(x => x.DoSomething()).Returns(1);

This way when your foo method is called, it will call the DoSomething and always will return 1 ;)

Upvotes: 5

Ilya Palkin
Ilya Palkin

Reputation: 15797

You should not change anything if you have an interface IFoo and want to mock Foo class that has constructor with parameters.

Your code is exactly what you need.

var foo = new Mock<IFoo>();

The following advice covers the situations when the class has no interface and no parameterless constructor. Actually you can pass all needed parameters into constructor of Mock.

var mock = new Mock<IFoo>("constructor", "arguments");

but

"The best thing to do would be right click on your class and choose Extract interface." (c)

Upvotes: 9

Zoran Horvat
Zoran Horvat

Reputation: 11301

Interfaces are useful when one type has more than one implementation. On a negative side, this means that you should take care not to derive interfaces just because you want interfaces (common mistake). On a positive side, mocked interface is the second implementation by definition.

So, the conclusion is - if a type acts as some other type's dependency, then it is a good candidate to implement an interface. In that case you will be able to mock the interface in unit tests freely and fully.

On a related note, when defining an interface, make sure to only add functional parts to the interface: methods that define what the object does, not what it looks like. Having an interface with a bunch of getters/setters does not add value to the design. This is quite large area of theory, and this tiny window is not the place to write more about it.

To clarify connection with your question: mocked implementation should provide behavior required by the interface. To do that, you use features of the mocking framework. This has nothing to do with concrete implementation of the Foo class - you define specific behavior of Mock object.

Upvotes: 0

Related Questions