简体   繁体   中英

C# wpf UnitTesting viewmodels

I'm trying to unit test my viewmodels in a wpf application. I have a command in my viewmodel which executes a method containing a confirmation dialog. I need to run all unit tests, so that each time opening these dialogs it requires manual confirmation.

The question I have is there any way i can programmatically know which method have confirmation dialog and programmatically click "Ok" or "Cancel"?

The best solution to this is probably not to try to click Ok or Cancel programmatically, but to prevent the creation of the dialogs while running the unit tests.

To do this, you need an abstraction for getting a user confirmation, something like this:

public interface IUserConfirmation
{
    bool Confirm(string title, string message);
}

In the Execute-method of your command, you only use this abstraction instead of actually showing a dialog:

public class ViewModel 
{
    private void MyCommandExecuted(object parameter)
    {
        if (this.confirmation.Confirm("Please confirm", "Are you sure you want to ...?")
        {
            ...
        }
    }

Now you create two implementations of this interface: One which actually shows a dialog to the user and another one which simply returns a preconfigured value. In your main application, you use the "real" dialog implementation and in your unit tests you use the "fake" implementation.

In order to do that, you need to be able to "inject" different implementations in your ViewModel, for example via the constructor:

public ViewModel(IUserConfirmation confirmation)
{
    if (confirmation == null)
        throw new ArgumentNullException("confirmation");

    this.confirmation = confirmation;
}

private readonly IUserConfirmation confirmation;

This is actually a well-known pattern called "dependency injection". There are frameworks available which can help you with the creation of objects, but for simple cases like this one they're not necessary.

Here's how the two implementations could look like:

public class MessageBoxUserConfirmation : IUserConfirmation
{
    public bool Confirm(string title, string message)
    {
        return MessageBox.Show(title, message) == true;
    }
}

public class TestUserConfirmation: IUserConfirmation
{
    public bool Result { get; set; }

    public bool Confirm(string title, string message)
    {
        return this.Result;
    }
}

In your unit test, you use it like this:

var confirmation = new TestConfirmation();
var viewModel = new ViewModel(confirmation);

// simulate a user clicking "Cancel"
confirmation.Result = false;

viewModel.MyCommand.Execute(...);

// verify that nothing happened

There are also frameworks for creating these fake implementations without having to write your own classes all the time, but again, for simple cases like that you probably won't need them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM