问题
I need to asset an action called by a mock component.
public interface IDispatcher
{
void Invoke(Action action);
}
public interface IDialogService
{
void Prompt(string message);
}
public class MyClass
{
private readonly IDispatcher dispatcher;
private readonly IDialogservice dialogService;
public MyClass(IDispatcher dispatcher, IDialogService dialogService)
{
this.dispatcher = dispatcher;
this.dialogService = dialogService;
}
public void PromptOnUiThread(string message)
{
dispatcher.Invoke(()=>dialogService.Prompt(message));
}
}
..and in my test..
[TestFixture]
public class Test
{
private IDispatcher mockDispatcher;
private IDialogService mockDialogService;
[Setup]
public void Setup()
{
mockDispatcher = MockRepository.GenerateMock<IDispatcher>();
mockDialogService = MockRepository.GenerateMock<IDialogService>();
}
[Test]
public void Mytest()
{
var sut = CreateSut();
sut.Prompt("message");
//Need to assert that mockdispatcher.Invoke was called
//Need to assert that mockDialogService.Prompt("message") was called.
}
public MyClass CreateSut()
{
return new MyClass(mockDipatcher,mockDialogService);
}
}
Maybe I need to restructure the code, but confused on that. Could you please advise?
回答1:
You are actually testing this line of code:
dispatcher.Invoke(() => dialogService.Prompt(message));
Your class calls the mock to invoke a method on another mock. This is normally simple, you just need to make sure that Invoke is called with the correct arguments. Unfortunately, the argument is a lambda and not so easy to evaluate. But fortunately, it is a call to the mock which makes it easy again: just call it and verify that the other mock had been called:
Action givenAction = null;
mockDipatcher
.AssertWasCalled(x => x.Invoke(Arg<Action>.Is.Anything))
// get the argument passed. There are other solutions to achive the same
.WhenCalled(call => givenAction = (Action)call.Arguments[0]);
// evaluate if the given action is a call to the mocked DialogService
// by calling it and verify that the mock had been called:
givenAction.Invoke();
mockDialogService.AssertWasCalled(x => x.Prompt(message));
回答2:
You need first to put an expectation on your mock. For example I want to test that Invoke is called only once and that I don't care about the incoming parameters.
mockDispatcher.Expect(m => m.Invoke(null)).IgnoreArguments().Repeat.Once();
Then you have to assert and verify your expectations
mockDispatcher.VerifyAllExpectations();
you can do it the same way for the second mock, however it's a not good practice to have two mocks per unit test. You should test each in different tests.
For setting expectations please read http://ayende.com/wiki/Rhino+Mocks+Documentation.ashx
来源:https://stackoverflow.com/questions/6413040/how-to-assert-that-an-action-was-called