Pato
Pato

Reputation: 679

AutoMoqer: Passing parameters into constructors

When I'm in need to mock some class that goes like this:

public class Dummy
{
  private readonly int _someInt;
  private readonly int _someOtherInt;
  private readonly IFoo _foo;

    public Dummy(int someInt,int someOtherInt, IFoo foo)
    {
      _someInt = someInt;
      _someOtherInt = someOtherInt;
      _foo = foo;
    }
}

I use Moq to do something like this:

[Test]
public void ShouldCreateADummyInstance()
{
      var someInt = 1;
      var someOtherInt = 2;

      var mockFoo = new Mock<IFoo>();

      var dummy = new Dummy(someInt, someOtherInt, mockFoo.Object);

      //And so on...
}

But when I use AutoMoq I can't specify a different int for each dependency (I mean someInt and someOtherInt) into my constructor because AutoMoqer.SetInstace(instanceIWantToUse) sets the same specified instance each time that has to supply that dependecy.

Do you know how can I specify a different int for someInt and someOtherInt in order to keep using AutoMoqer in my tests ?

Thanks, hope you can help me out!

Upvotes: 4

Views: 4585

Answers (2)

FlyingFoX
FlyingFoX

Reputation: 3509

Solution similar to Moq

You can create an instance of Dummy in AutoMoq very similar as you do in Moq. This does not future proof your testcode against changes in the constructor parameters, but may still be acceptable.

var mocker = new AutoMoqer();
var fooMock = mocker.GetMock<IFoo>();
var dummy = new Dummy(1, 2, fooMock.Object);
// test something about dummy

Solution with AutoMoq

If you really want to future proof your TestCode, then it may be neccessary to change the constructor to depend on interfaces.

interface IDummyParameters {
    int SomeInt {get;set;}
    int SomeOtherInt {get;set;}
}

public class Dummy {
    public Dummy(IDummyParameters parameters, IFoo foo){
        ...
    }
}

Then you can create your Dummy class with AutoMoq like this:

var mocker = new AutoMoqer();
mocker.GetMock<IDummyParameters>.Setup(x => x.SomeInt).Returns(1);
mocker.GetMock<IDummyParameters>.Setup(x => x.SomeOtherInt).Returns(2);
// notice how this code does not say anything about IFoo.
// It is created automatically by AutoMoq
var dummy = mocker.Create<Dummy>();

Upvotes: 1

Erik Dietrich
Erik Dietrich

Reputation: 6090

Full disclosure: I've never used AutoMoq (though I did just sign up to follow it on GitHub since it looks intriguing and I like things that cut down on boilerplate).

That said, it looks like the AutoMoq tool was designed for a different use case than yours. It appears that he uses it to "future proof" against broken unit tests if another constructor injected dependency is added, and to be able to generate a default object with something there for the dependencies, presumably to avoid null reference exceptions.

I would assume after reading the AutoMoq project page that if Darren were writing your particular unit test, he would probably just use Moq out of the box. That is, for that particular test, you should probably go with the test that you have posted. AutoMoq appears to aim at supplying sensible default behavior for when you don't want to bother specifying all of your dependencies in a test. But in your case, you do want to specify those particular dependencies.

Just because you use regular Moq for that particular test doesn't mean that you can't use AutoMoq for other tests. The rest of your tests (where both ints are zero or whatever) will be future-proofed, but you may just have to live with that one breaking if you add another constructor parameter to your Dummy class.

(You could also always snag the source code for AutoMoq and modify it to your needs).

Upvotes: 2

Related Questions