Модульное тестирование зависимых методов - PullRequest
10 голосов
/ 09 марта 2009

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

// This would work
MyClass myClass1 = new MyClass(mockDevice);
myClass1.Run(myDatastructure);
myClass1.Stop();

// This would throw an InvalidOperationException
MyClass myClass2 = new MyClass(mockDevice);
myClass2.Stop();

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

В любом случае я хотел бы протестировать различные пост-условия вызова Stop, но я бы не хотел звонить Run, потому что я тестирую Stop - не Run! Я хотел бы что-то вроде этого:

MyClass myClass = new MyClass(mockDevice);
myClass.Stop();
Assert.IsTrue(mockDevice.ResetCalled);

Пока что я вижу только одно возможное решение, а именно: создание TestableMyClass, которое наследуется от MyClass, что позволяет установить правильное внутреннее состояние экземпляра MyClass перед вызовом Stop. Проблема с этим решением состоит в том, что я должен изменить свою реализацию MyClass, чтобы иметь защищенные члены вместо частных, и мне не нравится идея изменить реализацию для тестирования это!

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

Ответы [ 3 ]

6 голосов
/ 09 марта 2009

Насколько я понимаю, вы уже тестируете Stop двумя способами, в которых его можно использовать (с запущенной операцией и без нее). Пока mockDevice делает свою работу, мне кажется, что вы тестируете его разумно. В идеале вы должны быть в состоянии проверить команды, отправленные на устройство и т. Д. (Что большинство фальшивых фреймворков сделает проще).

5 голосов
/ 09 марта 2009

В этой ситуации лично у меня было бы два теста для этого:

  1. Тест без вызова Run (), вызываемого первым. Я бы проверил, действительно ли это исключение. Я также проверил бы, являются ли почтовые условия такими, какими я их ожидаю.
  2. Тест с вызовом Run () первым. Я бы протестировал только те почтовые условия, которые я ожидаю.

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

EDIT: Я понимаю, почему вы не хотите вызывать run до остановки - вы думаете, что в случае сбоя run, тест, который должен только тестировать метод stop, скорее всего также будет неудачным.

Однако я хотел бы предположить, что у вас также есть тест для метода run. Это означает, что при выполнении тестов, которые тестируют поведение тестов метода pass - stop метода run, также должны пройти. Если тесты метода запуска не пройдены, то результаты тестов метода запуска не определены - они могут или не могут.

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

1 голос
/ 09 марта 2009

Это не поможет решить вашу непосредственную проблему, но я предпочитаю отображать состояние отображения, а не объекты с различными режимами.

IdleDevice idle = new IdleDevice(mockDevice);
RunningDevice running = idle.Run(myDatastructure);
running.Stop();

// This would not compile, as IdleDevice has no Stop method
IdleDevice idle = new IdleDevice(mockDevice);
idle.Stop();

Если вы не можете скомпилировать невозможные ситуации, вам не нужно проверять их.

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