Carna

Assertion Object

If you want to assert property values of an object altogether, it can be done with the AssertionObject class as follows;

  1. creates the class inherited from the AssertionObject class.
  2. defines properties you want to assert in it and specifies the AssertionPropertyAttribute attribute for them.
  3. creates each instance from expected and actual values, and asserts them.
class User
{
    public string FirstName { get; }
    public string LastName { get; }
    public int Age { get; }
}
class UserAssertion : AssertionObject
{
    [AssertionProperty]
    public string FirstName { get; }
    [AssertionProperty]
    public string LastName { get; }
    [AssertionProperty]
    public int Age { get; }

    private UserAssertion(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }

    public static UserAssertion Of(string firstName, string lastName, int age) => new(firstName, lastName, age);
    [return: NotNullIfNotNull("user")]
    public static UserAssertion? Of(User? user)
        => user is null ? null : new UserAssertion(user.FirstName, user.LastName, user.Age);
}
ExpectedUser = UserAssertion.Of("John", "Smith", 32);
When("to retrieve a user", () => User = UserRepository.GetById(1));
Then($"the user should be as follows:{ExpectedUser.ToDescription()}", () => UserAssertion.Of(User) == ExpectedUser);

If the ToDescription method defined in the AssertionObject class is called in a description for a step as above, the description is output as follows;

When to retrieve a user
Then the user should be as follows:
    FirstName: John
    LastName: Smith
    Age: 32

If you want to change the label of the property, the Description property of the AssertionPropertyAttribute attribute is specified.

[AssertionProperty("First Name")]
public string FirstName { get; }

If you want to do an assertion that is other than an equality for example not equal, less than, or etc., you define the property with the class inherited from the AssertionProperty class.

For example, an assertion that an age of a user is greater than or equal to 20 is defined as follows;

class UserAssertion : AssertionObject
{
    [AssertionProperty]
    public string FirstName { get; }
    [AssertionProperty]
    public string LastName { get; }
    public AssertionProperty<int> Age { get; }

    private UserAssertion(string firstName, string lastName, AssertionProperty age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }

    public static UserAssertion Of(string firstName, string lastName, int age)
        => new(firstName, lastName, new GreaterThanOrEqualAssertion<int>(age));
    [return: NotNullIfNotNull("user")]
    public static UserAssertion? Of(User? user)
        => user is null ? null : new UserAssertion(user.FirstName, user.LastName, new ActualValueProperty<int>(user.Age));
}
ExpectedUser = UserAssertion.Of("John", "Smith", 20);
When("to retrieve a user", () => User = UserRepository.GetById(1));
Then($"the user should be as follows:{ExpectedUser.ToDescription()}", () => UserAssertion.Of(User) == ExpectedUser);

Then the description is as follows;

When to retrieve a user
Then the user should be as follows:
    FirstName: John
    LastName: Smith
    Age: greater than or equal 20

Note: when the type of the assertion property is the type inherited from the AssertionProperty class, the AssertionPropertyAttribute attribute does not have to be specified except to have to specify the description.

The classes inherited from the AssertionProperty class defined by the Carna are as follows;

Class Description
EqualAssertionProperty asserts whether an actual value is equal to an expected value.
NotEqualAssertionProperty asserts whether an actual value is not equal to an expected value.
LessThanAssertionProperty asserts whether an actual value is less than an expected value.
LessThanOrEqualAssertionProperty asserts whether an actual value is less than or equal to an expected value.
GreaterThanAssertionProperty asserts whether an actual value is greater than an expected value.
GreaterThanOrEqualAssertionProperty asserts whether an actual value is greater than or equal to an expected value.
EnumerableAssertionProperty asserts whether an actual enumerable is sequence equal to an expected enumerable.
ActualValueProperty uses to specify an actual value and can't assert any other assertion properties.