The Problem
So I’ve been working on an MVVM WPF application as a side project and wanted to get good practice in things like TDD (and better MVVM). I’m just not sure how to go about unit testing my code and was wondering what you guys think.
I’ll go and post some of my Model and ViewModel classes and maybe you guys can see what is needed to be tested.
MainViewModel.cs
public class MainViewModel : ViewModelBase { #region - Event Handlers - public DialogClosingEventHandler AddTeamDialogClosingEventHandler { get; private set; } #endregion // - Event Handlers - #region - Private Properties - private Team _selectedTeam; private Soldier _selectedSoldier; #endregion // - Private Properties - #region // - Public Properties - public ObservableCollection<Soldier> Soldiers { get; set; } public ObservableCollection<Team> Teams { get; } public Team SelectedTeam { get => _selectedTeam; set { _selectedTeam = value; RaisePropertyChanged(nameof(SelectedTeam)); } } public Soldier SelectedSoldier { get => _selectedSoldier; set { _selectedSoldier = value; RaisePropertyChanged(nameof(SelectedSoldier)); } } #endregion // - Public Properties - #region // - Commands - public ICommand DeleteTeamCommand { get; private set; } public ICommand AddSoldierDialogCommand { get; private set; } #endregion // - Commands - #region - Services - public IDialogService AddSoldierDialogService { get; private set; } #endregion // - Services - #region - Constructors - public MainViewModel() { Soldiers = new ObservableCollection<Soldier>(); Teams = new ObservableCollection<Team>(); Soldiers.CollectionChanged += Soldiers_CollectionChanged; Teams.CollectionChanged += Teams_CollectionChanged; DeleteTeamCommand = new RelayCommand(DeleteTeam); AddSoldierDialogCommand = new RelayCommand(AddSoldierDialog); AddSoldierDialogService = new AddSoldierDialogService(); AddTeamDialogClosingEventHandler = AddTeamCommandDialogClosed; } #endregion // - Constructors - #region - Methods - private void AddTeamCommandDialogClosed(object sender, DialogClosingEventArgs eventargs) { var teamName = eventargs.Parameter as string; AddTeam(teamName); } private void AddTeam(string teamName) { Teams.Add( new Team { TeamName = teamName }); } private static void DeleteTeam() { } private void AddSoldierDialog() { AddSoldierViewModel addSoldierViewModel = new AddSoldierViewModel(); addSoldierViewModel.AddSoldierClicked += AddSoldierViewModel_AddSoldierClicked; AddSoldierDialogService.ShowDialog(addSoldierViewModel); } private void AddSoldierViewModel_AddSoldierClicked(object sender, AddSoldierEventArgs e) { Soldiers.Add(new Soldier(e.Soldier)); AddSoldierDialogService.CloseDialog(); } private void Teams_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (var item in e.NewItems) { } } if (e.OldItems != null) { foreach (var item in e.OldItems) { } } } private void Soldiers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (var item in e.NewItems) { } } if (e.OldItems != null) { foreach (var item in e.OldItems) { } } RaisePropertyChanged(nameof(Soldiers)); } #endregion // - Methods - }
AddSoldierViewModel.cs
Note: This class is bound to a AddSoldierView which is basically a form which the User could fill out for the Soldier to be added eventually to the MainViewModel via AddSoldierClicked Event
public class AddSoldierViewModel : ViewModelBase { public event EventHandler<AddSoldierEventArgs> AddSoldierClicked; private Soldier _soldier; public Soldier Soldier { get => _soldier; set { _soldier = value; RaisePropertyChanged(nameof(Soldier)); } } public ICommand AddSoldierCommand { get; set; } public AddSoldierViewModel() { AddSoldierCommand = new RelayCommand(AddSoldier); Soldier = new Soldier(); } private void AddSoldier() { OnAddSoldierClicked(new AddSoldierEventArgs() { Soldier = Soldier }); } protected virtual void OnAddSoldierClicked(AddSoldierEventArgs e) { var handler = AddSoldierClicked; handler?.Invoke(this, e); } }
Soldier.cs
public class Soldier : ObservableObject { private string _firstName; private string _lastName; private SoldierType? _soldierType; private Rank _rank; private Team _primaryTeam; private Team _secondaryTeam; public string FirstName { get => _firstName; set { Set(() => FirstName, ref _firstName, value); RaisePropertyChanged(nameof(FullName)); } } public string LastName { get => _lastName; set { Set(() => LastName, ref _lastName, value); RaisePropertyChanged(nameof(FullName)); } } public string DisplayName => $ "{Rank} {LastName}, {FirstName}"; public string FullName => $ "{FirstName} {LastName}"; public SoldierType? SoldierType { get => _soldierType; set { Set(() => SoldierType, ref _soldierType, value); } } public Rank Rank { get => _rank; set { Set(() => Rank, ref _rank, value); } } public Team PrimaryTeam { get => _primaryTeam; set { Set(() => PrimaryTeam, ref _primaryTeam, value); } } public Team SecondaryTeam { get => _secondaryTeam; set { Set(() => SecondaryTeam, ref _secondaryTeam, value); } } public Soldier() { FirstName = null; LastName = null; SoldierType = Enums.SoldierType.Rookie; Rank = Rank.Rookie; } public Soldier(Soldier copySoldier) { FirstName = copySoldier.FirstName; LastName = copySoldier.LastName; SoldierType = copySoldier.SoldierType; Rank = copySoldier.Rank; PrimaryTeam = copySoldier.PrimaryTeam; SecondaryTeam = copySoldier.SecondaryTeam; } }
Team.cs
public class Team : ObservableObject { private string _teamName; private ObservableCollection<Soldier> _mainSoldiers; private ObservableCollection<Soldier> _alternateSoldiers; public string TeamName { get => _teamName; set { Set(() => TeamName, ref _teamName, value); } } public ObservableCollection<Soldier> MainSoldiers { get => _mainSoldiers; set { Set(() => MainSoldiers, ref _mainSoldiers, value); } } public ObservableCollection<Soldier> AlternateSoldiers { get => _alternateSoldiers; set { Set(() => AlternateSoldiers, ref _alternateSoldiers, value); } } public Team() { MainSoldiers = new ObservableCollection<Soldier>(); AlternateSoldiers = new ObservableCollection<Soldier>(); } }