Reputation: 760
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
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
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