Проверить, что преобразование применяется к конкретным полям

Есть класс, который предназначен для корректировки регистра ФИО (типовой сценарий: приход ФИО в верхнем регистре из СМЭВ):

public class ContactCorrectCaseInName : IContactCorrectCaseInName
{
    #region Dependencies

    private readonly IStringCorrectCase StringCorrectCase;

    #endregion

    public ContactCorrectCaseInName()
        : this(new StringCorrectCase())
    {
    }

    public ContactCorrectCaseInName(IStringCorrectCase stringCorrectCase)
    {
        this.StringCorrectCase = stringCorrectCase;
    }

    public void Execute(Contact contact)
    {
        contact.Lastname = this.StringCorrectCase.Execute(contact.Lastname);
        contact.Firstname = this.StringCorrectCase.Execute(contact.Firstname);
        contact.Middlename = this.StringCorrectCase.Execute(contact.Middlename);
    }
}

Можно написать тест, который проверяет конкретные значения полей:

    [Test]
    public void Test1()
    {
        // Arrange
        var contact = new Contact { Lastname = "ИВАНОВ", Firstname = "ИВАН", Middlename = "ИВАНОВИЧ"};
        var contactCorrectCaseInName = new ContactCorrectCaseInName();

        // Act
        contactCorrectCaseInName.Execute(contact);

        // Assert
        Assert.AreEqual("Иванов", contact.Lastname);
        Assert.AreEqual("Иван", contact.Firstname);
        Assert.AreEqual("Иванович", contact.Middlename);
    }

И что делается вызов методов:

    [Test]
    public void Test2()
    {
        // Arrange
        var contact = new Contact { Lastname = "ИВАНОВ", Firstname = "ИВАН", Middlename = "ИВАНОВИЧ"};
        var corrector = A.Fake<IStringCorrectCase>();
        var contactCorrectCaseInName = new ContactCorrectCaseInName(corrector);
        A.CallTo(() => corrector.Execute("ИВАНОВ")).Returns("Иванов");
        A.CallTo(() => corrector.Execute("ИВАН")).Returns("Иван");
        A.CallTo(() => corrector.Execute("ИВАНОВИЧ")).Returns("Иванович");

        // Act
        contactCorrectCaseInName.Execute(contact);

        // Assert
        Assert.AreEqual("Иванов", contact.Lastname);
        Assert.AreEqual("Иван", contact.Firstname);
        Assert.AreEqual("Иванович", contact.Middlename);
    }

Мне кажется, что хотя поставленный тест выполняет свою задачу — он является достаточно хрупким: мы не можем проверить явно, что преобразование применяется к конкретному полю. Фактически, у теста есть знание о том, что определённые данные поступают в определённые поля и вот на этом предположении и строится тест.

Можно ли как-то (для nUnit или другого известного вам фреймворка тестирования) убрать вот эту хрупкость? (Желательно без изменения тестируемого класса)

Идеальный тест на мой взгляд проверяет две вещи: а) что к определённым полям применяется определённый метод и что б) ко всем остальным не применяется.


Ответы (1 шт):

Автор решения: A K

Пока решил остановиться на таком варианте, но возможно у кого есть идеи получше:

[Test]
public void Always_ModifiesNames()
{
    // Arrange
    var contact = new Contact { Lastname = "string1", Firstname = "string2", Middlename = "string3" };
    var propNames = new[] { nameof(Contact.Lastname), nameof(Contact.Firstname), nameof(Contact.Middlename), };
    var corrector = GetCorrector(contact, propNames);
    var contactCorrectCaseInName = new ContactCorrectCaseInName(corrector);

    // Act
    contactCorrectCaseInName.Execute(contact);

    // Assert
    Assert.AreEqual(contact.Lastname.ToUpper(), contact.Lastname);
    Assert.AreEqual(contact.Firstname.ToUpper(), contact.Firstname);
    Assert.AreEqual(contact.Middlename.ToUpper(), contact.Middlename);
}

private IStringCorrectCase GetCorrector(Contact contact, string[] propNames)
{
    var corrector = A.Fake<IStringCorrectCase>();

    foreach (var propName in propNames)
    {
        var val = GetValue(contact, propName);
        A.CallTo(() => corrector.Execute(val)).Returns(val.ToUpper());
    }

    return corrector;
}

Да, здесь нет проверки, что остальные поля не затрагиваются, но по крайней мере более наглядно видно, что изменение применяется именно к определённым свойствам.

→ Ссылка