Property Tests
Note
The property accessor being tested will prefix the test method identifier. For example, if you are testing the set
accessor of a property, the test identifier would begin Set
.
Example 1 - Set Accessor Throws Exception
Test Case:
# | Test Case | Test Data | Expected |
---|---|---|---|
1 | Exception when the value is a negative value | Value: -1 | ArgumentOutOfRangeException, Parameter: value, Message: The value must be zero or greater., State is not updated. |
Testing Goal: Set the property to an invalid value.
C#
[TestMethod]
public void SetAmountOfMoney_ToValueLessThanZero_ThrowsException()
{
// Arrange
string name = "Kenny";
decimal amountOfMoney = 100;
Person person = new Person(name, amountOfMoney);
// Act & Assert
ArgumentOutOfRangeException exception = Assert.ThrowsException<ArgumentOutOfRangeException>(() => person.AmountOfMoney = -1);
// Assert exception state
Assert.AreEqual("value", exception.ParamName);
Assert.AreEqual("The value must be zero or greater.", GetExceptionMessage(exception.Message));
// Reflection
PrivateObject target = new PrivateObject(person);
// Obtain object state
decimal actual = (decimal)target.GetField("amountOfMoney");
// Assert
Assert.AreEqual(amountOfMoney, actual);
}
Notes:
- The
Assert.ThrowsException()
method is used since an exception is expected to occur and the state of the exception is verified. - In most cases, when an exception is thrown in a
set
accessor, the state should not change to the invalid value. The finalAssert
statement verifies this.
Example 2 - Set Accessor Valid Value
Test Case:
# | Test Case | Test Data | Expected |
---|---|---|---|
3 | Sets the amount of money to zero | Initial amount of money: 100, Value: 0 | 0 |
Testing Goal: Sets the property to a valid value and verifies the state changed.
C#
[TestMethod]
public void SetAmountOfMoney_ToZero_StateUpdated()
{
// Arrange
string name = "Kenny";
decimal amountOfMoney = 100;
Person person = new Person(name, amountOfMoney);
decimal expected = 0;
// Act
person.AmountOfMoney = expected;
// Reflection
PrivateObject target = new PrivateObject(person);
// Obtain object state
decimal actual = (decimal)target.GetField("amountOfMoney");
// Assert
Assert.AreEqual(expected, actual);
}
Notes:
- When testing a modification in state, the value you choose to change the state should be different than the initial value.
- The variable
expected
is a recommended practice as it makes theAssert
statement clearer. - Due to the result of the unit changing the state, accessing the
private
field is required to verify the test.
Example 3 - Get Accessor
Test Case:
# | Test Case | Test Data | Expected |
---|---|---|---|
4 | Gets the amount of money | Initial amount of money: 100 | 100 |
Testing Goal: Initialize the object and obtain its state.
C#
[TestMethod]
public void GetAmountOfMoney_ReturnsState()
{
// Arrange
string name = "Kenny";
decimal amountOfMoney = 100;
Person person = new Person(name, amountOfMoney);
// Act
decimal actual = person.AmountOfMoney;
// Assert
Assert.AreEqual(amountOfMoney, actual);
}
Notes:
- The test method identifier does not require the scenario part.
PrivateObject
should not be used in this test as noprivate
member is accessed.
Auto-Implemented Property Tests
When a property is auto-implemented, it will not have a field you can access. When you are in this situation, you will use the GetProperty()
method of the PrivateObject
class.
C#
public abstract class Shape
{
public double XCoordinate { get; set; }
}
public class Circle : Shape
{
}
C#
[TestMethod]
public void SetXCoordinate_ToNewCoordinate_StateUpdated()
{
// Arrange
string color = "Black";
double radius = 77.7;
double xCoordinate = 123.4;
Circle circle = new Circle(color, radius);
// Act
circle.XCoordinate = xCoordinate;
PrivateObject target;
target = new PrivateObject(circle);
double actual = (double)target.GetProperty("XCoordinate");
// Assert
Assert.AreEqual(xCoordinate, actual);
}