Andrew
Andrew

Reputation: 760

Constructor arguments cannot be passed for interface mocks - MOQ

So I have a unit test which uses a method in a class called ImpositionCalculatorManager. In this class I use dependency injection so I can access the methods on another class called ImpositionCalculatorRepository.

The ImpositionCalculatorManager looks like this:

 public class ImpositionCalculatorManager : IImpositionCalculatorManager {
        private readonly IImpositionCalculatorRepository _impositionCalculatorRepository;
        public ImpositionCalculatorManager(IImpositionCalculatorRepository impositionCalculatorRepository) {
            _impositionCalculatorRepository = impositionCalculatorRepository;
        }
        public ComboBoxItem[] ReturnInkDataSource() {
            return _impositionCalculatorRepository.ReturnInkDataSource();
        }

        public ComboBoxItem[] ReturnCoatingDataSource() {
            return _impositionCalculatorRepository.ReturnCoatingDataSource();
        }
    }
}

In my unit test I mock the ImpositionCalculatorManager and pass in a mocked version ImpositionCalculatorRepository into the constructor for the manager class.

However I get the error Constructor arguments cannot be passed for interface mocks.

This is what my unit test fixture looks like:

 public class ImpositionCalculatorPresenterTestFixture {
        private ImpositionCalculatorPresenter _impositionCalculatorPresenter;
        private readonly SystemVariablesPresenter _systemVariablesPresenter;
        private readonly Mock<IImpositionCalculatorManager> _mockImpositionCalculatorManager;
        private readonly Mock<ISystemVariablesView> _mockSystemVariablesView;
        private readonly Mock<IPrintingDesignManager> _mockPrintingDesignManager;
        private readonly Mock<ISystemVariablesManager> _mockSystemVariablesManager;
        private readonly Mock<IImpositionCalculatorRepository> _mockImpositionCalculatorRepo;
        private Mock<IImpositionFormView> _mockView;

        public ImpositionCalculatorPresenterTestFixture() {
            _mockImpositionCalculatorRepo = new Mock<IImpositionCalculatorRepository>();
//Error occurs on the below line
            _mockImpositionCalculatorManager = new Mock<IImpositionCalculatorManager>(_mockImpositionCalculatorRepo.Object);
            _mockSystemVariablesView = new Mock<ISystemVariablesView>();
            _mockPrintingDesignManager = new Mock<IPrintingDesignManager>();
            _mockSystemVariablesManager = new Mock<ISystemVariablesManager>();
            _systemVariablesPresenter = new SystemVariablesPresenter(_mockSystemVariablesView.Object, _mockSystemVariablesManager.Object);
        }

 [TestMethod]
        public void PopulateInkDataSources_ApplicationOnLoad_InkDataSourcesPopulatedWithDataFromJSON() {
            //Arrange
            SetupImpostionPresenter();
            _mockView.SetupProperty(r => r.InkSideOneDataSource);
            _mockView.SetupProperty(r => r.InkSideTwoDataSource);
            _mockImpositionCalculatorManager.Setup(r => r.ReturnInkDataSource())
                .Returns<ComboBoxItem[]>
                (x => new ComboBoxItem[] {
                        new ComboBoxItem("Test", 1 ),
                        new ComboBoxItem("Test 2", 2)
                });

            //Act
            _mockView.Raise(r => r.FormOnLoad += null, new EventArgs());

            //Assert
            Assert.IsTrue(_mockImpositionCalculatorManager.Object.ReturnInkDataSource()
                == _mockView.Object.InkSideOneDataSource && _mockImpositionCalculatorManager.Object.ReturnInkDataSource()
                == _mockView.Object.InkSideTwoDataSource
                );
        }

private void SetupImpostionPresenter() {
            _mockView = new Mock<IImpositionFormView>();
            _impositionCalculatorPresenter = new ImpositionCalculatorPresenter(_mockView.Object,
            _mockImpositionCalculatorManager.Object, _mockSystemVariablesManager.Object, _systemVariablesPresenter,
            _mockPrintingDesignManager.Object);
        }
    }
}

I've looked on stack overflow and people are saying that it's because an interface doesn't have a constructor and only the class does and that I shouldn't have to pass anything into the constructor but when I remove the constructor arguments from the mock, I receive the error Parameter count mismatch when trying to setup a method from the manager.

I would just like to mock the manager so I can setup a method to return the values which I have already set.

Why will this not work?

Upvotes: 0

Views: 2380

Answers (2)

0xb304
0xb304

Reputation: 93

ok I reproduced your Parameter count mismatch problem. Try these two changes:

1) (as previously discussed) create your manager without any constructor and without any other dependencies; and

2) fix the Func given to the ReturnInkDataSource mock: change this:

    _mockImpositionCalculatorManager.Setup(r => r.ReturnInkDataSource())
            .Returns<ComboBoxItem[]>
            (x => new ComboBoxItem[] {
                    new ComboBoxItem("Test", 1 ),
                    new ComboBoxItem("Test 2", 2)
            });

to

    _mockImpositionCalculatorManager.Setup(r => r.ReturnInkDataSource())
            .Returns(
                () => new ComboBoxItem[] {
                        new ComboBoxItem("Test", 1 ),
                        new ComboBoxItem("Test 2", 2)
                      }
              );

First change is foundational DI/mocking -- we don't need mocks for mocks.

Second change is Moq specific -- it's necessary because the params for the lambda given to Returns() must match the params provided in Setup() -- see Moq + Unit Testing - System.Reflection.TargetParameterCountException: Parameter count mismatch

Upvotes: 1

0xb304
0xb304

Reputation: 93

I'm assuming you're trying to test the concrete ImpositionCalculatorPresenter implementation? I'm also assuming that this ImpositionCalculatorPresenter implementation is expected to respond to a FormOnLoad event.

If my assumptions are correct, then your _mockImpositionCalculatorManager.Setup(r => r.ReturnInkDataSource()).Returns<ComboBoxItem[]> (...)) should be sufficient and would not require a backing IImpositionCalculatorRepository mock or impl or anything -- your goal of "I would just like to mock the manager" seems to be handled by this moq setup, which fakes the guts of the manager which the ImpositionCalculatorPresenter needs.

Upvotes: 0

Related Questions