Как я могу проверить частные методы с помощью DUnit?

У меня есть класс, который я тестирую с помощью DUnit. В нем есть несколько методов: некоторые общедоступные методы и частные методы.

type
  TAuth = class(TDataModule)
  private
    procedure PrivateMethod;
  public
    procedure PublicMethod;
  end;

Чтобы написать unit test для этого класса, я должен сделать все методы общедоступными.

Есть ли другой способ объявить частные методы, чтобы я мог их протестировать, но они не являются общедоступными?

Ответы

Ответ 1

Вам не нужно публиковать их. Защищено будет. Затем вы можете подтипировать класс для модульного тестирования и обработать защищенные методы. Пример:

type
  TAuth = class(TDataModule)
  protected
    procedure MethodIWantToUnitTest;
  public
    procedure PublicMethod;
  end;

Теперь вы можете подтипировать его для вашего unit test:

interface

uses
  TestFramework, Classes, AuthDM;

type
  // Test methods for class TAuthDM
  TestAuthDM = class(TTestCase)
     // stuff
  end;

  TAuthDMTester = class(TAuthDM)
  public
    procedure MethodIWantToUnitTestMadePublic;
  end;

implementation

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
  MethodIWantToUnitTest;
end;

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

Ответ 2

Это немного глупо, но я думаю, что это самый простой и понятный подход. Используйте эту директиву условной компиляции:

  {$IfNDef TEST}
  private
  {$EndIf}

Ваш unit тестовый проект должен определять TEST в project → conditional defines. Без указания видимости они становятся опубликованными.

Осторожно: если приватная видимость не первая в объявлении класса, она получит предыдущее определение. Более безопасный, но более подробный и менее понятный способ:

  private
  {$IfDef TEST}
  public
  {$EndIf}

Это имеет много преимуществ по сравнению с подклассами или другими подходами:

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

Я думаю, что это более четкое решение и лучше, чем выбранный ответ.

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

Ответ 3

Я рекомендую книгу " Тестовые шаблоны XUnit " Джерарда Месароса:

Тест-специфичный подкласс

Вопрос: Как мы можем сделать код тестируемым, когда нам нужен доступ к закрытому состоянию SUT?

Ответ: Добавьте методы, которые показывают состояние или поведение, необходимое для теста, в подкласс SUT.

... Если тестируемая система (SUT) не была специально разработана для тестирования, мы можем обнаружить, что тест не может получить доступ к состоянию, которое он должен инициализировать или проверить в какой-то момент теста.

В статье также объясняется, когда его использовать и какие риски он несет.

Ответ 4

Поместите код DUnit внутри своего устройства. Затем вы можете получить доступ к чему угодно.

Ответ 5

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

Ответ 7

{$IFNDEF UNITEST}
private
{$ENDIF}

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