0

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?

Andrew
  • 720
  • 3
  • 9
  • 34
  • Looks like you are missing Mock declaration here `private readonly Mock _impositionCalculatorPresenter;` – Ripon Jun 02 '17 at 22:40
  • My presenter isn't an interface and I would have to make all my methods virtual and I don't want to do this. Would doing this make a difference anyway? – Andrew Jun 02 '17 at 22:46

2 Answers2

1

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

0xb304
  • 93
  • 7
  • Ahh, I understand. The parameter count mismatch issue wasn't to do with the repository at all. It was that I mocked my `ReturnInkDataSource` to accept a `ComboBoxItem[]` and I didn't pass one in. Thank you for staying committed. I appreciate the help – Andrew Jun 04 '17 at 05:09
0

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.

0xb304
  • 93
  • 7
  • I am trying to test the concrete `ImpositionCalculatorPresenter` and yes the presenter responds to the `FormOnLoad` event. I also would've thought that my implementation was correct. The manager method calls the repository to attempt to return data. – Andrew Jun 03 '17 at 03:46
  • The manager method `ReturnInkDataSource()` appears to be mocked correctly, no need to involve the repository at all. – 0xb304 Jun 03 '17 at 04:20
  • sorry meant to be more detailed. I'd expect that when you change manager mock to just `_mockImpositionCalculatorManager = new Mock();`, then it would compile. If you make this change then what error do you get? – 0xb304 Jun 03 '17 at 04:25
  • once I do this and it calls the method in the manager it throws the exception 'Parameter count mismatch' – Andrew Jun 04 '17 at 04:55