Skip to content

Auto-implemented Properties

Earlier in this chapter, you learned that tests related to an object's state are verified by evaluating the field within the class (or base class). Since C# allows you to create Auto-implemented properties, the (backing) field an auto-implemented property creates is not accessible to you. Therefore, the PrivateObject class is needed to access the auto-generated field.

For the following example, we'll say that the "name" attribute of the Person class is defined as an Auto-implemented property.

Test Case:

# Test Case Test Data Expected
4 Initialize the name Parameter name: "Kenny", Parameter amountOfMoney: 500 "Kenny"

Testing Goal: The goal of this test is to initialize the state of the object and verify it did so correctly.

C#
[TestMethod]
public void Constructor_NameIsKenny_InitializeState()
{
    // Arrange
    string name = "Kenny";
    decimal amountOfMoney = 500;

    // Act
    Person person = new Person(name, amountOfMoney);

    // Reflection
    PrivateObject target = new PrivateObject(person);

    // Obtain object state
    string actual = (string)target.GetProperty("Name");

    // Assert
    Assert.AreEqual(name, actual);
}

Notes:

  • Because this is a state-related test, the PrivateObject class is used to gain access to the class' backing field.
  • The GetProperty() method is used to access the backing field created by the auto-implemented property. The argument is the identifier of the property you want to access the backing field for.
    • Using the GetField() method in this context would raise an exception, since the class would not declare a field with the specified identifier.

It would not be the proper practice to do the following:

C#
[TestMethod]
public void Constructor_NameIsKenny_InitializeState()
{
    // Arrange
    string name = "Kenny";
    decimal amountOfMoney = 500;

    // Act
    Person person = new Person(name, amountOfMoney);

    // Obtain object state
    string actual = person.Name;

    // Assert
    Assert.AreEqual(name, actual);
}

Notes:

  • This test does not test the unit in isolation.

Modifying State

Depending how a class is designed, you may experience situations where you cannot initialize the object to the specific state you need for the test using any of the constructor methods defined in the class.

As previously mentioned, you must avoid invoking other parts of the class in your test, so using the set accessor of a property would be forbidden. It is also possible that the set accessor may not be defined or accessible.

When faced with this situation, you will use the PrivateObject class to modify the state of the object without invoking any of its class members.

The following test determines that when you ToggleOscillation() to a Fan while it is currently oscillating, the state will change such that it is no longer oscillating. When a Fan is initialized, it is always not oscillating. None of the constructors in the Fan class allow you to change this state. In order to verify that the ToggleOscillation() performs its task correctly, the Fan must be oscillating before the ToggleOscillation() method is invoked.

It should also be noted that the IsOscillating property is auto-implemented.

C#
[TestMethod]
public void ToggleOscillation_TurnOffOscillation_UpdateState()
{
    // Arrange
    OscillatingFan fan = new OscillatingFan();

    PrivateObject target = new PrivateObject(fan);

    target.SetProperty("IsOscillating", true);

    // Act
    fan.ToggleOscillation();

    // Assert
    bool expected = false;

    bool actual = (bool)target.GetProperty("IsOscillating");

    Assert.AreEqual(expected, actual);
}

Notes:

  • Because this is a state-related test, the PrivateObject class is used to gain access to the class' field.
  • The SetProperty() method is used to change the backing field value. The first argument indicates the identifier of the property that you want to access the backing field for, and the second argument is the value you want to change the backing field to.

It would not be the proper practice to do the following:

C#
[TestMethod]
public void ToggleOscillation_TurnOffOscillation_UpdateState()
{
    // Arrange
    OscillatingFan fan = new OscillatingFan();

    // This is not good
    fan.ToggleOscillation();

    // This is also not good
    //fan.IsOscillating = false;

    // Act
    fan.ToggleOscillation();

    // Assert
    bool expected = false;

    bool actual = (bool)target.GetProperty("IsOscillating");

    Assert.AreEqual(expected, actual);
}

Notes:

  • This test does not test the unit in isolation.