Я считаю, что тестирование частных/защищенных методов зависит от того, где/как они доступны, и что тестируется.
Если я создаю многоразовую библиотеку общего кода, тогда частные и защищенные методы в этих классах проверяются в рамках тестовых примеров библиотеки.Эти тесты гарантируют, что код нижнего уровня работает, чтобы я мог верить в библиотеку.
Теперь, когда я пишу бизнес-приложение, которое обращается к этой библиотеке, я не пишу тесты для объектов библиотеки, так как они будут издеваться над тестами для бизнес-приложения. Тесты библиотеки показывают, что библиотека работает, а затем тесты бизнес-приложений показывают, что приложение работает.
Бизнес-приложение не пытается проверить частные/защищенные методы библиотеки, поскольку я считаю, что черный ящик кода, о котором я не знаю (похож на внешнюю библиотеку или веб-службу). Тем не менее, я проверяю частные и защищенные методы бизнес-приложения в наборе тестов для бизнес-приложения, чтобы убедиться, что методы/функции ведут себя так, как должны.
В качестве примера то, предположим следующие бизнес-классы (очень кратко передать мысль, а не функции):
<?php
class ACCOUNTS
{
protected GetEstimation()
{
...
return $CalculatedValue;
}
}
class CUSTOMER_ACCOUNT extends ACCOUNTS
{
protected GetEstimation()
{
$BaseEstimation = parent::GetEstimation();
...
return $NewCalculatedValue
}
}
class RESELLER_ACCOUNT extends ACCOUNTS
{
protected GetEstimation()
{
...
return $ResellerCalculatedValue; // Note: No call to parent
}
}
?>
В этом примере существуют различные значения, которые будут возвращены. Была использована функция Protected, поэтому ее можно было переопределить, и она не должна полагаться на функциональность родительского класса. В этом примере я хочу протестировать все эти классы, возвращая правильные значения, когда они используются.
Базовый класс ACCOUNTS должен возвращать оценку после выполнения своих вычислений на основе значений класса. Как правило, я просто установить значения и проверить возвращения:
<?php
class ACCOUNTSTest extends PHPUnit_Framework_TestCase
{
protected $Accounts;
protected function setUp()
{
$this->Accounts = new ACCOUNTS();
}
public function testEstimationHome()
{
$this->Accounts->InternalValue1 = 1;
$this->Accounts->InternalValue2 = 10;
$this->Accounts->InternalValue3 = 100;
$this->assertEquals(523, $this->Accounts->GetEstimation(), 'Test Home Account with values 1, 10, 1000');
}
public function testEstimationHome2()
{
$this->Accounts->InternalValue1 = 5;
$this->Accounts->InternalValue2 = 2;
$this->Accounts->InternalValue3 = 10;
$this->assertEquals(253, $this->Accounts->GetEstimation(), 'Test Home Account with values 5, 2, 10');
}
protected function tearDown()
{
unset($this->Accounts);
}
}
?>
Эти тесты теперь гарантировать, что ACCOUNTS-> GetEstimation() работает правильно. Затем я тестировал CUSTOMER_ACCOUNT и имел аналогичные тесты, чтобы убедиться, что класс правильно вычисляет.
Да, если базовый класс изменяется, тогда мне может потребоваться обновить тесты в CUSTOMER_ACCOUNT, поскольку ACCOUNTS-> GetEstimation() изменен, но у меня также есть дополнительная проверка, что базовый класс все еще корректно возвращается.
В качестве альтернативы я мог бы изменить эту структуру и использовать Injection Dependency для предоставления определенной информации (ACCOUNTS), чтобы гарантировать, что если родительская оценка всегда была 523, тогда этот класс возвращает правильные значения. Если ACCOUNTS изменяет полученную оценку, и это не имеет значения для этого класса (возможно, этот класс просто добавляет дополнительные значения), тогда я изолирую свой тест и не нуждаюсь в беспокойстве.
Надеюсь, это обновление поможет проиллюстрировать то, что я говорю.
Я проголосовал за то, чтобы закрыть, в основном, на основе мнения. Я думаю, что это вызовет слишком много дискуссий без фактических ответов. –
Есть много вопросов (и ответов) о SO о том, как сделать не ту вещь ... :) –
@ DuncanJones Ok. Затем я прошу вас предложить мне, что делать, если у меня есть это сомнение. – Geek