2009-03-09 2 views
9

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

// 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, чтобы иметь защищенные члены вместо частных членов, а I не делает, как идея изменить реализацию, чтобы проверить ее!

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

ответ

6

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

+0

Итак, вы думаете, что можно просто вызвать Run, Stop, Assert? – toxvaerd

+0

Да, я так думаю. А также стоит упомянуть Stop without Run для проверки необходимого исключения. В конечном счете, недействительно сначала вызвать Stop without Run ... –

4

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

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

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

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

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

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

+0

Я уже тестирую Stop-метод, который генерирует исключение, но я вижу вашу точку! – toxvaerd

+1

Спасибо, за ваш ответ, но я собираюсь принять ответ Марка Гравелла, поскольку он был первым :-) – toxvaerd

1

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

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(); 

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

+0

Мне нравится этот дизайн! Я подумаю об использовании этого, но пока я просто проведу Stop, а затем Run. благодаря – toxvaerd

Смежные вопросы