Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MVVM - Unit Testing a command - Private vs Public methods?

Basically, If I use MVVM and expose public ICommands, should my delegates be public or private?

like image 332
michael Avatar asked Jul 28 '11 18:07

michael


3 Answers

I would make them private - they aren't part of your class's public interface, that's what the public ICommand properties are for.

like image 166
Dan J Avatar answered Sep 30 '22 16:09

Dan J


Personally, I'd go with private methods and I'll tell you why. You're exposing an ICommand, which to me says that the consuming view should call a CanExecute prior to calling an Execute. If they don't, they're going against the API and shooting themselves in the foot and at that point it is out of your hands. Just like if someone used reflection to set an important private variable to null and broke your class design because of this... shooting themselves in the foot. So why make the members private? Because there is no need to expose members that should not be called directly.


Basically, when you unit test the members you don't do so individually, you do so in the way the API intends for the members to be executed. So, you're not really testing the members, but moreover you're testing the command, which again means they should be tested in a pair in the specific order of:

if (CanExecute)
{
    Execute;
}
like image 27
myermian Avatar answered Sep 30 '22 18:09

myermian


I have MVVM for something simple control of increase, decrease buttons and Slider show value.

If you have test ICommand and INotifyPropertyChanged, you can make kind of UnitTest:

[TestMethod]
public void TestViewModel3()
{
    int min = -10;
    int max = 10000;
    int initVal = 50;
    bool initState = false;

    ToglledSliderModel model = new ToglledSliderModel(initState, initVal, min, max);
    ToglledSliderViewModel viewModel = new ToglledSliderViewModel();
    viewModel.Model = model;

    int status = 567;
    viewModel.PropertyChanged += delegate
    {
        status = 234;
    };

    for (int i = 1; i < 100; i++)
    {
        status = 567;
        ICommand ic = viewModel.IncreaseValue;
        ic.Execute(this);
        Thread.Sleep(2);
        Assert.AreEqual(status, 234);
        Assert.AreEqual(model.SliderValue, initVal + i);
    }
}

you can see, i test INotifyPropertyChanged behaviour and ICommand executing

like image 43
zzfima Avatar answered Sep 30 '22 16:09

zzfima