Я изучаю искусство тестирования и мне нужна ваша помощь. У меня есть функция (устаревший код), которую нужно протестировать, эта функция получает некоторые данные в качестве параметров, временно сохраняет их в базе данных и отправляет во внешний API. Если ответ API равен 200, тогда данные в таблице обновляются, чтобы сохранить их определенным образом, в противном случае они удаляются.
Это код:
public function sendAssignments(Challenge $challenge, int $reportType)
{
$reportModel = new Report($challenge, $reportType);
$pointsList = $this->calculateAssignments($challenge, $reportType);
$pharmsToSend = $pointsList['pharmsCollection'];
$pointsArray = $pointsList['pointsArray'];
$savedAt = Date('Y-m-d H:i:s');
$symfonyService = new SymfonyService();
$requestUid = \uniqid('AS-', false);
$sentAt = Date('Y-m-d H:i:s');
$reportModel->persistReportAssignments($pharmsToSend, $savedAt, $sentAt, false);
$symfonyResult = $symfonyService->sendReportPoints(
$requestUid,
$challenge->challenge_id,
$pointsArray
);
if ($symfonyResult->code == "200") {
// Actualizamos los datos
$reportModel->persistReportAssignments($pharmsToSend, $savedAt, $sentAt, true);
FlashMessage::addSuccess('Se han asignado los puntos del reporte.', 'Asignación correcta');
} else {
$reportModel->deleteFailedAssignmentsFromDatabase($savedAt);
FlashMessage::addError($symfonyResult->msg, 'Error '.$symfonyResult->code.' - No se han asignado los puntos');
}
if ($reportType == Report::REPORT_CONNECTED) {
return redirect()->route('reports.showConnectedReport', ['challenge'=>$challenge]);
} else if ($reportType == Report::REPORT_MANUAL) {
return redirect()->route('reports.showManualReport', ['challenge'=>$challenge]);
}
}
Я тестирую функцию, а невызов API, поэтому я хочу издеваться над классом SymfonyService, для этого я написал новый класс:
class SymfonyServiceMock
{
public function sendReportPoints()
{
return ["operation"=>"ok", "code" => 200];
}
}
Но проблема в том, что SymfonyService создается внутри функции, поэтому я не могу использовать класс SymfonyServiceMockсмоделировать вызов API. И вот мое сомнение, могу ли я провести рефакторинг этой функции, чтобы передать ей SymfonyService? Правильный ли это подход?
Я имею в виду такой рефакторинг, как этот:
public function sendAssignments(Challenge $challenge, int $reportType, SymfonyService $symfonyService)
{
// The rest of the code here, but without instantiating SymfonyService
}
Если у вас есть еще одна лучшая идея о том, как это будет наилучшим способом ее тестирования (следуя принципам SOLID)конечно) Я был бы рад узнать.
Заранее большое спасибо
РЕДАКТИРОВАТЬ: У меня была эта идея, я зарегистрировал SymfonyService на AppServiceContainer, итеперь я внедряю SymfonyService в контроллер, чтобы я мог выполнить рефакторинг следующим образом:
public function sendAssignments(Challenge $challenge, int $reportType)
{
$this->executeSendAssignmentsOperation($challenge, $reportType);
if ($reportType == Report::REPORT_CONNECTED) {
return redirect()->route('reports.showConnectedReport', ['challenge'=>$challenge]);
} else if ($reportType == Report::REPORT_MANUAL) {
return redirect()->route('reports.showManualReport', ['challenge'=>$challenge]);
}
}
public function executeSendAssignmentsOperation(Challenge $challenge, int $reportType)
{
$reportModel = new Report($challenge, $reportType);
$pointsList = $this->calculateAssignments($challenge, $reportType);
$pharmsToSend = $pointsList['pharmsCollection'];
$pointsArray = $pointsList['pointsArray'];
$savedAt = Date('Y-m-d H:i:s');
$sentAt = Date('Y-m-d H:i:s');
$reportModel->persistReportAssignments($pharmsToSend, $savedAt, $sentAt, false);
$symfonyResult = $this->_symfonyService->sendReportPoints(
$challenge,
$pointsArray,
$reportType
);
$sentAt = Date('Y-m-d H:i:s');
if ($symfonyResult->code == "200") {
// Actualizamos los datos
$reportModel->persistReportAssignments($pharmsToSend, $savedAt, $sentAt, true);
FlashMessage::addSuccess('Se han asignado los puntos del reporte.', 'Asignación correcta');
} else {
$reportModel->deleteFailedAssignmentsFromDatabase($savedAt);
FlashMessage::addError($symfonyResult->msg, 'Error '.$symfonyResult->code.' - No se han asignado los puntos');
}
}
С этим рефактором теперь я могу написать тест. Но мне все еще интересно, является ли это правильным подходом к проблеме. Если нет, не могли бы вы объяснить, почему?