1

I'm writing an application in MVVM with so far good results. But I am doing work in the ViewModel which raises an error, which I want to show to the user to let them know.

I can just do something like this in my ViewModel (VM):

MessageBox.Show(errorMessage);

or more likely something like:

new ErrorMessageWindow(errorMessage).ShowDialog()

so I can style it.

The problem is then I am creating a UI popup from the VM. I'm creating unit tests for the application which also pop up the window and stop running until it's manually closed.

Looking for a good approach.

I was considering raising an event in the VM - but since the View really has no knowledge of the VM or its properties I don't know how I would subscribe to it.

I'm not using any external Frameworks - I'd rather implement anything myself.

heltonbiker
  • 26,657
  • 28
  • 137
  • 252
jb.
  • 1,848
  • 9
  • 27
  • 43

3 Answers3

4

I've generally provided the viewmodel with a way to signal that it needs an error raised. You can do this through dependency injection, pass it to the constructor, etc. The implementation is provided by the containing application or the bound view.

When you test, you then pass in a test implementation of the "show error message" functionality that just verifies whether it was called and whether it requested the correct error message. Ideally, you restrict the viewmodel to passing a resource name and an array of arguments to the format string so that it works with internationalization as well.

MNGwinn
  • 2,394
  • 17
  • 18
3

You should work against an abstraction so that you can swap out the implementation during unit tests.

For example you could have an IWindowManager interface with a ShowDialog method, and then one implementation that calls MessageBox (or whatever technique you want during production), and then you can use an isolation framework or create a test implementation for unit tests which return the result you want as your control variables in your test.

You really should think about using an MVVM framework, and something like Caliburn.Micro already has an IWindowManager interface.

devdigital
  • 34,151
  • 9
  • 98
  • 120
2

I would recommend that you move away from the traditional Win32 dialogs. If anything it is better to have the dialog done in WPF, and raise it from the ViewModel using for example a dialog bound to a bool for visibility. This would be easily testable, as you wouldn't even need to create a mock class of your Window Manager.

A simple example on how make your own pop-up dialog in WPF is available here.

You can also find an alternative implementation using a dialog service here to help you move the creation of the dialog box from your ViewModel. This allows you to mock the dialog service during unit-testing.

Community
  • 1
  • 1
eandersson
  • 25,781
  • 8
  • 89
  • 110