Reputation: 1833
I am writing a unit test in WPF with Moq to test whether or not a user clicked the "Yes" button on a YesNoCancel
MessageBox when they are closing the window. In my CloseCommand
I have in my ViewModel gives the following message when the user is closing the window:
var result = _messageSvc.Show(
"Do you want to save changes?",
"Save Changes",
Services.MessageBoxButton.YesNoCancel,
Services.MessageBoxIcon.Question,
Services.MessageBoxResult.Yes);
My _messageSvc
is a private instance inside of a custom Messaging service to display messageboxes. Here is the code for the service:
public interface IMessageSvc
{
void Show(string message);
MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult = 0);
}
public class MessageSvc : IMessageSvc
{
public void Show(string message)
{
MessageBox.Show(message);
}
public MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult)
{
return (MessageBoxResult)MessageBox.Show(message, caption, (System.Windows.MessageBoxButton)buttons, (System.Windows.MessageBoxImage)icon, (System.Windows.MessageBoxResult)defaultResult);
}
}
Note: MessageBoxButton
, MessageBoxIcon
, and MessageBoxResult
are enumerations I made in the same file to mimic what .NET provides out of the box. I am not showing them here for sake of readability
My unit test is:
[TestMethod]
public void ShouldAskToSaveOnCloseRespondYesTest()
{
// Mock and setup initial user data
var u= new User
{
UserId = 1,
UserName = "FirstName LastName",
FavoriteColor = "Blue"
};
mainViewModel.UserInfo= new UserInfoDtoWrapper(u);
// assert the data has not changed yet
Assert.IsFalse(mainViewModel.UserInfo.IsChanged);
// change the user data
mainViewModel.UserInfo.UserName= "LastName FirstName";
// assert the data has changed
Assert.IsTrue(mainViewModel.UserInfo.IsChanged);
// execute window closing
mainViewModel.CloseCommand.Execute(new object());
// verify messagebox shows and the 'Yes' button is clicked
// this will then save the changes made to the user instance
var messageBox = new Mock<IMessageSvc>();
messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"),
It.Is<string>(y => y == "Save Changes"),
It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel),
It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question),
It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes)))
.Returns(MessageBoxResult.Yes);
messageBox.Verify();
}
The error comes on the messageBox.Verify()
line, but from what I can see I am doing it correctly. I need to get the return value of the messagebox to continue testing what happens after the user clicks the "Yes" button, so I did not want to use Verify
with a Linq query inside, instead I need to capture the result.
Thanks
Upvotes: 1
Views: 1533
Reputation: 11841
Currently you are setting up your mocked method after testing the code that would call it. Re-arrange your test into the AAA (Arrange, Act, Assert) pattern like so:
var messageBox = new Mock<IMessageSvc>();
messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"),
It.Is<string>(y => y == "Save Changes"),
It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel),
It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question),
It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes)))
.Returns(MessageBoxResult.Yes);
mainViewModel.CloseCommand.Execute(new object());
messageBox.Verify(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"),
It.Is<string>(y => y == "Save Changes"),
It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel),
It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question),
It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes)));
Upvotes: 1
Reputation: 15197
This won't work. You have 2 issues in your test code:
You first fire the CloseCommand
(which is assumed to call the IMessageSvc.Show
method), and only then setup a mock for that service.
You setup a new mock for a service but don't use it.
To correct these errors:
Here is an example:
class MainViewModel
{
private readonly IMessageSvc _messageSvc;
public MainViewModel(IMessageSvc svc)
{
this._messageSvc = svc;
}
}
[TestMethod]
public void ShouldAskToSaveOnCloseRespondYesTest()
{
// Arrange
var messageBox = new Mock<IMessageSvc>();
messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"),
It.Is<string>(y => y == "Save Changes"),
It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel),
It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question),
It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes)))
.Returns(MessageBoxResult.Yes)
.Verifiable();
var mainViewModel = new MainViewModel(messageBox.Object);
// Act
mainViewModel.CloseCommand.Execute(new object());
// Assert
messageBox.Verify();
}
Upvotes: 2