Sobes.tech
Middle

Каква е разликата между stop и mock?

sobes.tech AI

Отговор от AI

stop — това е техника за изолиране на теста от директни зависимости (например, обаждания към външни API, бази данни) чрез замяна на реалните обекти с тестови заглушки. Тя се използва за контрол на поведението на външните зависимости и осигуряване на възпроизводимост на тестовете.

mock (от "mock object") — това е вид тестова заглушка, която не само заменя реален обект, но и позволява да се проверява как тестираният код взаимодейства с него. С помощта на mock-ове може да се твърди (assert) за извикванията на методи, техните аргументи и брой на извиквания.

Следователно, stop е по-общо понятие, описващо изолацията, а mock е конкретен инструмент за постигането ѝ, който добавя възможност за верификация на взаимодействието.

Пример с използване на PHPUnit и Mockery:

<?php

use PHPUnit\Framework\TestCase;
use Mockery;

// Клас, използващ външна зависимост
class UserProcessor
{
    private $apiClient;

    public function __construct(ApiClient $apiClient)
    {
        $this->apiClient = $apiClient;
    }

    public function processUserData(int $userId): bool
    {
        $data = $this->apiClient->fetchUserData($userId);

        if ($data && $data['status'] === 'active') {
            // Логика за обработка на активен потребител
            return true;
        }
        return false;
    }
}

// Пример за използване на mock за тестване
class UserProcessorTest extends TestCase
{
    public function testProcessUserDataWithActiveUser()
    {
        // Създаване на mock за ApiClient
        $apiClientMock = Mockery::mock(ApiClient::class);

        // Настройване на очаквано поведение за mock
        // Очаква се извикване на метода fetchUserData с аргумент 123
        $apiClientMock->shouldReceive('fetchUserData')
                      ->with(123)
                      ->andReturn(['status' => 'active', 'data' => '...']) // Mock връща тези данни
                      ->once(); // Очакваме методът да бъде извикан точно веднъж

        // Създаване на тествания обект, предавайки му mock
        $userProcessor = new UserProcessor($apiClientMock);

        // Изпълнение на тествания метод
        $result = $userProcessor->processUserData(123);

        // Проверка на резултата
        $this->assertTrue($result);

        // Проверка, че всички очаквания на mock са изпълнени
        Mockery::close();
    }
}

В този пример ApiClient се заменя с "mock". Ние "заглушихме" реалното извикване на API и едновременно с това настроихме mock да връща определени данни при извикване на fetchUserData(123). Освен това, проверяваме, че този метод е бил извикан с правилните аргументи и точно веднъж. Това е ключовата разлика: mock позволява да се проверява взаимодействието.