Dialogs are common in any windows application. Dialogs provide challenges for unit-testing, as unit-tests are meant to run without user intervention. This is not possible if a dialog box keeps on popping when you run the unit-tests.
One way to solve the problem is to add a Boolean variable to stop the dialog from popping. It is set to True by default, so that usually, we see the dialog. It is set to False during unit-testing. It will increase your code coverage (in my test project it increased the coverage from 55% to 77.50%). To get better and "think" coverage, it is necessary to mock the dialog using an interface class.
In the test project, I have created a FileDialogDemo project and its corresponding test-project named FileDialogDemo.Tests. FileDialogDemo opens the standard Windows "Open File" dialog and shows the selected file in a text-box. This project includes the "Boolean flag" approach to increase some coverage. As a comparison, I have added a TestableFileDialog and its corresponding TestableFileDialog.Tests projects that shows the changes to make the dialog testable.
To unit-test the dialog we have to do the following steps:
-
Create an interface that can be mocked (e.g. by using Moq). It should include the methods and properties that we would like to mock
- We created a IOpenFileDialog class with FileName and ShowDialog() method
-
Create a wrapper class that implements the interface. It would create an object of original dialog and have "pass-through" methods/properties to this object
- In the demo, its name is OpenFileDialogWrapper
-
In the ViewModel code that is calling the showing the dialog, we create another method that takes the interface object as parameter. This will contain all the functionality of show the dialog and processing the results.
- In the demo, its internal void BrowseFile(IOpenFileDialog dialog)
- The original method will call the method (added above) by passing the instance of the wrapper class.
- In the unit-test, we test the method that take the interface and pass a mocked version to simulate user behavior (like pressing OK or Cancel)
A comparison of code changes is as follows
Before
- public void BrowseFile()
- {
- if (AllowShowDialog)
- {
- using (var dialog = new OpenFileDialog())
- {
- if (dialog.ShowDialog() == DialogResult.OK)
- {
- FilePath = dialog.FileName;
- }
- }
- }
- }
After
- public void BrowseFile()
- {
- using (var dialog = new OpenFileDialogWrapper())
- {
- BrowseFile(dialog);
- }
- }
- internal void BrowseFile(IOpenFileDialog dialog)
- {
- if (AllowShowDialog)
- {
- if (dialog.ShowDialog() == DialogResult.OK)
- {
- FilePath = dialog.FileName;
- }
- }
- }
The code coverage results show that now the coverage is 100% for the ViewModel.
1 comment:
Can you please share the sample code for interface and unit test. Thanks
Post a Comment