Lesson Wednesday

Now that we've created a ClearAll() method and tested that our GetAll() method successfully returns an empty list, let's continue testing and adding functionality to our application.

Returning a List of Items


The next simplest behavior is ensuring GetAll() can return a List of recently-created Items. We'll add the following test for this behavior:

ToDoList.Solution/ToDoList.Tests/ModelTests/ItemTests.cs
...

[TestMethod]
public void GetAll_ReturnsItems_ItemList()
{
  //Arrange
  string description01 = "Walk the dog";
  string description02 = "Wash the dishes";
  Item newItem1 = new Item(description01);
  Item newItem2 = new Item(description02);
  List<Item> newList = new List<Item> { newItem1, newItem2 };

  //Act
  List<Item> result = Item.GetAll();

  //Assert
  CollectionAssert.AreEqual(newList, result);
}

...
  • We arrange both description arguments, then create a new Item for each. We also manually create a List containing these Items. This represents what we anticipate receiving from GetAll().

  • We act by calling the static GetAll() method.

  • We assert that the return value of GetAll() should be the same as our manually-constructed newList.

Since we've already added the necessary code to our Item class to handle adding each newly created object to the static List and we've handled our persistence issue, all of our tests should pass.

Debugging in MSTest


Let's take a quick detour to talk about debugging in MSTest. Let's add a foreach loop that uses the Console.WriteLine() method into the act area of each of our two tests that use GetAll().

ToDoList.Solution/ToDoList.Tests/ModelTests/ItemTests.cs
...
using System; //We have to add this to use Console.WriteLine().

...

[TestMethod]
public void GetAll_ReturnsEmptyList_ItemList()
{
...
  //Act
  List<Item> result = Item.GetAll();

  foreach (Item thisItem in result)
  {
    Console.WriteLine("Output from empty list GetAll test: " + thisItem.Description);
  }
...
}

[TestMethod]
public void GetAll_ReturnsItems_ItemList()
{
  ...

  //Act
  List<Item> result = Item.GetAll();

  foreach (Item thisItem in result)
  {
    Console.WriteLine("Output from second GetAll test: " + thisItem.Description);
  }
...
}
...

Let's also comment out the body of our Dispose method:

...
public void Dispose()
{
  // Item.ClearAll();
}
...

The loops will print each Item's description into the console for us. After running dotnet test again, our tests will fail but also output some additional information:

Output from empty list GetAll test: test
Output from empty list GetAll test: Walk the dog.
Output from empty list GetAll test: Do the dishes

Output from second GetAll test: test
Output from second GetAll test: Walk the dog.
Output from second GetAll test: Do the dishes
Output from second GetAll test: Walk the dog
Output from second GetAll test: Wash the dishes

The outputs from our Console.WriteLine illustrate clearly that our GetAll() methods were returning data that wasn't specific to the test method that it was called in. The Items in the static list persisted from test to test. We needed a way to collect the garbage created by each test and dispose of it, and this is precisely what the Dispose method is now doing for us.

Console.WriteLine() is a powerful tool in debugging and can be used the same way we used console.log() in JavaScript to help us visually understand what values variables, properties, and methods return at that point in time. Note that Console.WriteLine() will only output to the terminal if the test fails. It's a useful debugging tool, but should not be expected to output useful information on successful tests.

Before we move on, let's not forget to uncomment our Dispose method body and remove the loops!

Our test file should look like this:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using ToDoList.Models;
using System;

namespace ToDoList.Tests
{
  [TestClass]
  public class ItemTests : IDisposable
  {

    public void Dispose()
    {
      Item.ClearAll();
    }

    [TestMethod]
    public void ItemConstructor_CreatesInstanceOfItem_Item()
    {
      Item newItem = new Item("test");
      Assert.AreEqual(typeof(Item), newItem.GetType());
    }

    [TestMethod]
    public void GetDescription_ReturnsDescription_String()
    {
      //Arrange
      string description = "Walk the dog.";

      //Act
      Item newItem = new Item(description);
      string result = newItem.Description;

      //Assert
      Assert.AreEqual(description, result);
    }

    [TestMethod]
    public void SetDescription_SetDescription_String()
    {
      //Arrange
      string description = "Walk the dog.";
      Item newItem = new Item(description);

      //Act
      string updatedDescription = "Do the dishes";
      newItem.Description = updatedDescription;
      string result = newItem.Description;

      //Assert
      Assert.AreEqual(updatedDescription, result);
    }

    [TestMethod]
    public void GetAll_ReturnsEmptyList_ItemList()
    {
      // Arrange
      List<Item> newList = new List<Item> { };

      // Act
      List<Item> result = Item.GetAll();

      // Assert
      CollectionAssert.AreEqual(newList, result);
    }

    [TestMethod]
    public void GetAll_ReturnsItems_ItemList()
    {
      //Arrange
      string description01 = "Walk the dog";
      string description02 = "Wash the dishes";
      Item newItem1 = new Item(description01);
      Item newItem2 = new Item(description02);
      List<Item> newList = new List<Item> { newItem1, newItem2 };

      //Act
      List<Item> result = Item.GetAll();

      //Assert
      CollectionAssert.AreEqual(newList, result);
    }
  }
}

Lesson 18 of 20
Last updated April 14, 2022