Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor with more than one instance of same type

I have a class with a constructor like this:

MyClass(MySetting, IMyService, IMyService, IMyService)

How can I use AutoFixture to create MyClass in this case? I know when it has only one IMyService param, we can use AutoMoq to Freeze a mock, but in this case I'm not sure we can Freeze three mocks because I think the last one will be used for all three parameters.

like image 683
kvuong Avatar asked Feb 02 '26 08:02

kvuong


1 Answers

Indeed, if you Freeze an object, you'll get the same object every time you ask for it; that's the point of Freeze.

What I usually do in such a situation is to add Inspection Properties to the class, because What you compose, you can also expose:

public class MyClass
{
    public MyClass(
        MySetting setting,
        IMyService service1,
        IMyService service2,
        IMyService service3)
    {
        this.Service1 = service1;
        this.Service2 = service2;
        this.Service3 = service3;
    }

    public IMyService Service1 { get; }
    public IMyService Service2 { get; }
    public IMyService Service3 { get; }

    public string DoIt()
    {
        return
            this.Service1.Whatever() +
            this.Service2.Whatever() +
            this.Service3.Whatever();
    }
}

You can use Mock.Get to get the Mock for each injected service, like demonstrated by this test:

[Fact]
public void AskTheSut()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var sut = fixture.Create<MyClass>();
    Mock.Get(sut.Service1).Setup(s => s.Whatever()).Returns("foo");
    Mock.Get(sut.Service2).Setup(s => s.Whatever()).Returns("bar");
    Mock.Get(sut.Service3).Setup(s => s.Whatever()).Returns("baz");

    var actual = sut.DoIt();

    Assert.Equal("foobarbaz", actual);
}

On a tangential note, as a design principle I'd say that one dependency is fine, two of the same dependency can also occasionally be appropriate, but if you have three, you should consider having a collection of them instead. (One, two, many...)

like image 81
Mark Seemann Avatar answered Feb 03 '26 20:02

Mark Seemann