I'm currently creating some unit tests with rhino mocks and I have a test that looks like below. However I keep getting this error message,
IOsgController.AddWindow(Whiteboard.Model.OsgWindowProps); Expected #1, Actual #0.
Which is due to the lambda function not being executed in _dispatcher.BeginInvoke(()=>_osgController.AddWindow)
. How do I make this Action
get executed in my unit tests?
public void the_load_command_is_triggered_which_executes_the_load_control_method()
{
// arrange
IOsgController osgController = MockRepository.GenerateMock<IOsgController>();
IDispatcher dispatcher = MockRepository.GenerateMock<IDispatcher>();
Action action = osgController.AddWindow;
OsgViewModel osgViewModel = new OsgViewModel(osgController, dispatcher);
// dispatcher and add window should be called in LoadControl
dispatcher.Expect(d => d.BeginInvoke(action)).WhenCalled(i => action());
osgController.Expect(x => x.AddWindow());
// act
osgViewModel.LoadCommand.Execute(new object());
// assert
osgController.VerifyAllExpectations();
}
Class under test is:
public class OsgViewModel : ViewModelBase
{
private readonly IOsgController _osgController;
private readonly IDispatcher _dispatcher;
public OsgViewModel(IOsgController osgController, IDispatcher dispatcher)
{
_osgController = osgController;
_dispatcher = dispatcher;
LoadCommand = new RelayCommand(LoadControl);
}
public ICommand LoadCommand { get; set; }
public void LoadControl()
{
// lambda is not being executed in unit test.
_dispatcher.BeginInvoke(
() => _osgController.AddWindow());
}
}
The reason why lambda function is not being executed in the test is the following:
There are 2 lambdas:
The one declared in test method:
Action action = osgController.AddWindow;
The other one declared in the class under test:
() => _osgController.AddWindow()
They do exactly the same but they are different.
That is why setup for dispatcher.Expect(d => d.BeginInvoke(action))
doesn't match to the actual action passed to BeginInvoke()
. As a result WhenCalled()
argument is not being triggered.
The one of solutions is to setup the stub for dispatcher.BeginInvoke()
which accepts any action and just executes it:
dispatcher
.Stub(d => d.BeginInvoke(Arg<Action>.Is.Anything))
.WhenCalled(opt => ((Action)(opt.Arguments[0]))());
Also, Do()
handler can be used instead of WhenCalled()
here. Then arguments cast isn't required:
dispatcher
.Stub(d => d.BeginInvoke(Arg<Action>.Is.Anything))
.Do((Action<Action>)(action => action()));
Hope that helps.