locked
WPf Unit Testing RRS feed

  • Question

  • What portions of MVVM can be unit tested ? Is it just the View Models or more than that ? Would i be able to test even Commands on the UI ?

    Thanks

    Rajaraman S


    RAJ - DeepMinds

    Thursday, November 13, 2014 5:01 AM

Answers

  • The point of using a view model (MVVM) for testability reasons is that you can test your application logic without the view, i.e. you run unit tests agains the view model class only. Since the commands should be defined in the view model class and contain the application/presentation logic, you don't need the view to be able to test this. You simply execute the commands of the view model directly from the unit tests, e.g.:

    YourViewModel vm = new YourViewModel();
    vm.YourCommand.Execute(null); //command performs application logic
    Assert....

    You can of course also run unit tests agains model classes, where your business logic should be defined.

    When it comes to testing the actual UI, i.e. the view that contains UI controls such as Buttons, ComboBoxes, etc., MVVM doesn't offer that much benefits. The MVVM pattern is all about separating the UI and the application logic so that you can test your application logic without the view. You will need to use some UI automation tool to be able to test the view by clicking the controls etc. Please refer to the following article for more information about this:

    Automating UI Tests In WPF Applications: http://msdn.microsoft.com/en-us/magazine/dd483216.aspx

    Here is another article that describes how to write a testable presentation layer using MVVM that should also be of interest for you:

    Writing a Testable Presentation Layer with MVVM: http://msdn.microsoft.com/en-us/magazine/dn463790.aspx

    Please remember to mark helpful posts as answer and/or helpful.

     

    Thursday, November 13, 2014 11:14 AM

All replies

  • Unit tests are also called fast tests because they're supposed to run like a thousand tests in seconds in your test run window and show you results.

    The idea being you can make a change, run tests, make another change, run tests... And do that many times a day.

    You can't do that if your tests involve UI or an actual database.

    Commands are usually about going manipulating some data which the ui might be bound to rather than manipulating the UI.

    .

    What I run fast tests against are viewmodels.

    I don't run them against UI at all.

    People test that.

    I also mock provide a mock data access layer so you're not dependent on particular records in the database or slowed down by accessing a real database.

    I recommend Specflow for fast tests if your application is at all data orientated.

    .

    You also usually need slow tests which will actually update the database.

    These are too slow to run routinely so I use a continuous integration approach for them.

    I recommend Jenkins.

    Thursday, November 13, 2014 9:22 AM
  • The point of using a view model (MVVM) for testability reasons is that you can test your application logic without the view, i.e. you run unit tests agains the view model class only. Since the commands should be defined in the view model class and contain the application/presentation logic, you don't need the view to be able to test this. You simply execute the commands of the view model directly from the unit tests, e.g.:

    YourViewModel vm = new YourViewModel();
    vm.YourCommand.Execute(null); //command performs application logic
    Assert....

    You can of course also run unit tests agains model classes, where your business logic should be defined.

    When it comes to testing the actual UI, i.e. the view that contains UI controls such as Buttons, ComboBoxes, etc., MVVM doesn't offer that much benefits. The MVVM pattern is all about separating the UI and the application logic so that you can test your application logic without the view. You will need to use some UI automation tool to be able to test the view by clicking the controls etc. Please refer to the following article for more information about this:

    Automating UI Tests In WPF Applications: http://msdn.microsoft.com/en-us/magazine/dd483216.aspx

    Here is another article that describes how to write a testable presentation layer using MVVM that should also be of interest for you:

    Writing a Testable Presentation Layer with MVVM: http://msdn.microsoft.com/en-us/magazine/dn463790.aspx

    Please remember to mark helpful posts as answer and/or helpful.

     

    Thursday, November 13, 2014 11:14 AM
  • Thanks. One last question 

    My View Model looks like this 

    public class MainViewModel : INotifyPropertyChanged{

    public MainViewModel()
            {
                InitializeCommands();
                //LoadPerson();
            }

    private Person _modelPerson;
            public Person ModelPerson
            {
                get { return _modelPerson; }
                set
                {
                    _modelPerson = value;
                    OnPropertyChanged("ModelPerson");
                }
            }

    private LoadPersonCommand _loadPersonCommand;
            public LoadPersonCommand LoadPersonCommand
            {
                get { return _loadPersonCommand; }
                set
                {
                    _loadPersonCommand = value;
                    OnPropertyChanged("LoadPersonCommand");
                }
            }

        



            #region Methods

            private void LoadPerson()
            {
                ModelPerson = new Person()
                {
                    FirstName = "Brian",
                    LastName = "Lagunas",
                };
            }

            private void InitializeCommands()
            {
                LoadPersonCommand = new LoadPersonCommand(LoadPerson);
            }

    }

    LoadPErsonCommand is bound to my view 

            <Button Grid.Row="4" Grid.ColumnSpan="2" Content="Load Person" Margin="10" Command="{Binding LoadPersonCommand}" />

    I am using NUnit 

      [Test]
            public void ShouldLoadPerson()
            {
                MainViewModel mainViewModel = new MainViewModel();
                mainViewModel.LoadPersonCommand.Execute(null);
                        }

    Since LoadPerson just sets the ModelPerson what do i test or Assert ? 



    RAJ - DeepMinds

    Thursday, November 13, 2014 1:49 PM
  • >>Since LoadPerson just sets the ModelPerson what do i test or Assert ?

    The Command creates Person object with the values "Brian" and "Lagunas" and sets the ModelPerson property to this object so you should simply assert that the Person property contains a Person object with these values:

        [TestMethod]
        public void ShouldLoadPerson() {
    
          MainViewModel vm = new MainViewModel();
          vm.LoadPersonCommand.Execute(null);
          Assert.IsNotNull(vm.ModelPerson);
          Assert.AreEqual(vm.ModelPerson.FirstName, "Brian");
          Assert.AreEqual(vm.ModelPerson.LastName, "Lagunas");
        }
    

    Please don't post several questions in the same thread but when you do, please remember to mark all helpful posts as answer.

     

    Thursday, November 13, 2014 3:07 PM