Как проверить сервисный метод, который скрывает тестовые данные - PullRequest
0 голосов
/ 28 февраля 2012

Только представьте, что мой метод контроллера asp.net mvc может иметь такой код:

testplanService.AddTestplan(testplan,template,release);

, который вызывает приведенный ниже реализованный метод обслуживания:

public TestplanService
{

public void AddTestplan(Testplan testplan, Template template, Release release)
        {
           testplan.CreatedAt = DateTime.Now;
           testplan.UserId = WindowsIdentity.GetCurrent().Name;
           testplan.Name = release.Name + " " + template.Name + " " + testplan.UserId + " " + testplan.CreatedAt;

           _provider.AddTestplan(testplan, template, release);                             
        }

}

Как я могу протестировать CreatedAt, UserId и свойство Name в ASSERT, когда я не знаю значений внутри этого метода?

Да, я знаю, что мог бы передать все 3 значения в объекте testplan, который в любом случае передается методу сервиса, НОКласс контроллера в mvc не должен иметь этих 3 строк логики.

Так что бы вы сделали?

1 Ответ

0 голосов
/ 28 февраля 2012

Только представьте, что мой метод контроллера asp.net mvc может иметь такой код:

testplanService.AddTestplan(testplan,template,release);

Я не хочу ничего такого представлять.Правильный путь заключается в том, что ваш контроллер работает с абстракциями, а не с реальными реализациями.Поэтому вместо того, чтобы зависеть от фактической реализации службы, эта переменная testplanService, которую вы используете в своем контроллере, будет простым интерфейсом или абстрактным классом, который будет введен в конструктор вашего контроллера.

Теперь в своем модульном тесте вы можете фактически смоделировать этот интерфейс и протестировать свой контроллер в отдельности.

Теперь давайте рассмотрим фактическую реализацию службы:

public void AddTestplan(Testplan testplan, Template template, Release release)
{
    testplan.CreatedAt = DateTime.Now;
    testplan.UserId = WindowsIdentity.GetCurrent().Name;
    testplan.Name = release.Name + " " + template.Name + " " + testplan.UserId + " " + testplan.CreatedAt;
    _provider.AddTestplan(testplan, template, release);                             
}

ТамЕсть пара проблем с этим методом.Прежде всего, это зависит от недетерминированных данных, таких как DateTime.Now, которые трудно провести модульное тестирование.У Мартина Фаулера есть хорошая статья о недетерминизме в модульных тестах.Это также зависит от текущего WindowsIdentity.Все это сложно для модульного тестирования, потому что ваш метод зависит от реальных реализаций, а не от работы с абстракциями.

Таким образом, вам придется абстрагироваться от тех понятий, стоящих за провайдерами, которые вы можете использовать в своем модульном тесте.Убедитесь, что все ваши компоненты слабо связаны между собой.Вам будет гораздо проще работать с ними изолированно.


ОБНОВЛЕНИЕ:

Как указано в разделе комментариев, здесь приведен пример того, как абстрагировать поиск по дате и времени:

Рассмотрим следующий класс:

public class WeekendTester
{
    public bool IsWeekendSoon()
    {
        return (int)DateTime.Now.DayOfWeek > 3;
    }
}

Очевидно, что модульное тестирование IsWeekendSoon очень сложно, так как оно будет зависеть от дня, когда выполняется ваш модульный тест.

Таким образом, чтобы устранить недетерминизм в этом методе, вы можете сделать следующее:

public class WeekendTester
{
    private readonly Func<DateTime> _dateTimeProvider;
    public WeekendTester(Func<DateTime> dateTimeProvider)
    {
        _dateTimeProvider = dateTimeProvider;
    }

    public bool IsWeekendSoon()
    {
        return (int)_dateTimeProvider().DayOfWeek > 3;
    }
}

Теперь все, что вам нужно, - это настроить вашу любимую инфраструктуру DI для внедрения () => DateTime.Nowв конструктор этого объекта и внутри вашего модульного теста вы можете легко смоделировать его:

[TestMethod]
public void Weekend_Is_Still_Far_Away_From_The_28_th_Of_February_2012()
{
    // arrange
    Func<DateTime> providerMock = () => new DateTime(2012, 2, 28);
    var sut = new WeekendTester(providerMock);

    // act
    var actual = sut.IsWeekendSoon();

    // assert
    Assert.IsFalse(actual);
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...