Как проверить метод Add в слое сервиса? - PullRequest
0 голосов
/ 03 апреля 2019

Я читал, что, как правило, частные методы не нуждаются в модульном тестировании, потому что они тестируются публичными методами. Так что мне делать на уровне сервиса?

У меня есть сервисный слой и метод для добавления статьи в базу данных. Этот метод проверяет логику статьи и ее файлов, а затем сохраняет ее через репозиторий:

public void AddArticle(ArticleDto article)
{
    CheckArticleFiles(article);

    CheckArticleTitle(article.Title);
    CheckArticleSummary(article.Summary);
    CheckArticleBody(article.Body);

    _articleRepository.AddArticle(article.MapToDbModel());
    _articleRepository.SaveChanges();
}

Все проверочные коды теперь общедоступны, чтобы разрешить их для тестирования, что, я думаю, не является правильным способом (из-за принципов ООП). А с другой стороны, если я изменю их на частные, они должны быть проверены методом AddArticle . В этом случае я думаю, что это не юнит-тестирование. потому что это не единица, и этот метод действует как оркестратор.

Такая ситуация возникает, если я использую модель домена, которая имеет свою собственную логику. И логика - самая важная часть для тестирования, которая не должна быть общедоступной и даже защищенной

Так в чем мои ошибки здесь?

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

Часто части интерфейсов предназначены для использования только в определенных контекстах (только во время конфигурации, только во время инициализации, только из определенных потоков, только из тестового кода, только в определенных состояниях системы, ...).Возможности языков программирования выражать это так, что создаются реальные технические барьеры, довольно ограничены (обычно у вас есть публичные и частные, часто защищенные, иногда немного больше) - и достаточно часто существуют приемы для преодоления барьеров, таких как публичные или частные декларации,например, в C ++ с использованием приемов препроцессора, в Java и аналогичных языках с использованием самоанализа.Например, в Python такие механизмы полностью заменены соглашениями - если вы не будете следовать им, рано или поздно вы потеряете.

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

В вашем случае вы хотели бы указать, что определенные функции должны рассматриваться как подробности реализации (private), но все же должны быть доступны для целей модульного тестирования.И, да, я согласен с тем, что может иметь больше смысла тестировать функции private напрямую, чем тестировать их косвенно на уровне обслуживания.Это, конечно, компромисс, но из моего опыта я также знаю такие случаи.

Самый простой подход (если язык, который вы используете, не предлагает никаких лучших трюков, таких как конструкция C ++ friend), как вы предложили, чтобы сделать методы общедоступными и документировать, что они не предназначены для использования.Если вы хотите сделать это более заметным, одна из возможностей - сделать функцию общедоступной, но выразить ограничения в использовании путем именования.Функция foo, которая должна использоваться только в тестах, может быть названа forTestingOnly_foo.Так как это делает также уродливым, когда функция вызывается в частном контексте, foo все еще может быть закрытой функцией с не приватной оболочкой forTestingOnly_foo.

Если вы можете установить соглашение об именах для такихВ сценариях вы можете создать простой инструмент проверки, который проверяет, что никто (кроме как из контекста тестирования) не обращается к любому из этих «общедоступных, но логически закрытых» методов, и использовать его в сборке, чтобы он не работал в случае обнаружения неправильного использования.Необходимость таких подходов во многом зависит от организационной культуры, в которой вы работаете.

1 голос
/ 03 апреля 2019

У меня были бы модульные тесты вокруг каждой части бизнес-логики.

 CheckArticleFiles(article);
 CheckArticleTitle(article.Title);
 CheckArticleSummary(article.Summary);
 CheckArticleBody(article.Body);

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

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

Одно замечание: метод Add должен что-то возвращать, чтобы вы могли хотя бы выполнить некоторые проверки работоспособности, например, вернуть уникальный идентификатор созданной статьи и таким образом узнать, действительно ли работает ваш метод, плюс он позволяет вам делать другие интересные вещи, такие как создание ссылки на недавно созданную статью, потому что теперь вы знаете идентификатор.

Очень сложно добавить больше видения, так как вы до сих пор не показали никакого полезного кода. Например, у меня был бы класс Article, куда пошла бы вся бизнес-логика. Репо и спасительная часть были бы вне этого. Наличие публичного метода, который проверяет заголовок, совсем не плохая вещь, он позволяет вам проверять вещи индивидуально, а не проверять все целиком в одном. Это зависит от того, как вы его используете.

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