Как предоставить фиктивный менеджер сущностей для проверки класса обслуживания? - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть класс обслуживания (OutletScraper) в моем приложении Symfony (3.4). Класс использует Entity Manager и сервис геокодирования, предоставляемый пакетом Bazinga Geocoder. Я успешно настроил оба, так что я могу вызывать их из своего класса обслуживания. Всякий раз, когда мне нужен сервис, я вызываю его из контейнера, чтобы менеджер сущностей и пакет геокодеров уже были добавлены в него.

При тестировании я понимаю, что могу издеваться над менеджером сущностей, а затем передать это моему тестовому классу. Когда я получаю доступ к классу обслуживания из контейнера, как мне переопределить то, что передается конструктору? то есть, чтобы я мог предоставить фиктивный менеджер сущностей вместо того, чтобы ему вводили реальный. Я попытался создать экземпляр объекта класса обслуживания вручную:

$outletScraper = new OutletScraper(new Provider(), $this->createMock(EntityManagerInterface::class));

Однако при этом я получаю следующую ошибку:

Error: Cannot instantiate interface Geocoder\Provider\Provider

Как мне правильно создать экземпляр этого класса? Нужно ли вызывать его из сервисного контейнера (для него установлено значение private)? Цени любую помощь.

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Я бы порекомендовал, чтобы, если вы пытаетесь протестировать эту услугу в одиночку, вы также должны высмеивать Geocoder\Provider\Provider.В противном случае ваши тестовые утверждения могут привести к различным результатам в зависимости от того, когда вы их запускаете.

Если вы собираетесь часто использовать этот макет, вы можете даже создать свой собственный класс тестирования, который реализует этот интерфейс, так что выВы можете самостоятельно подготовить различные результаты в своей тестовой среде.

0 голосов
/ 13 сентября 2018

Ваш макет менеджера сущностей работает нормально, проблема в провайдере геокодера. Также как EntityManagerInterface, Geocoder\Provider\Provider также является интерфейсом. Обслуживающий персонал библиотеки просто решил опустить суффикс.

Это означает, что вы не можете просто создать его, а вместо этого должны передать конкретный класс, реализующий интерфейс, например Geocoder\Provider\GoogleMaps\GoogleMaps, если вы действительно хотите выполнить вызов геокодирования или смоделировать провайдера как хорошо.

Если вы хотите проверить, работает ли ваш настроенный провайдер геокодирования, вы можете написать функциональный тест с использованием Symfony WebTestCase, который выглядит примерно так:

<?php

namespace AppBundle\Tests\Scraper;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class OutletScraperTest extends WebTestCase
{
    public function testFindsLocation()
    {
        // This will instantiate your Symfony application in the test environment
        $client = static::createClient();

        $container = $client->getContainer();
        // Replace the class name with the service id, if you use artificial service ids like "app.outlet_scraper"
        $scraper = $container->get(OutletScraper::class);

        // Call whatever method you want to test on your outlet scraper
        $result = $scraper->someMethod();

        // Assert result matches expectations
        $this->assertEquals(..., $result);
    }
}

Будьте осторожны, поскольку при этом будет использоваться OutletScraper, настроенный для вашего приложения, с обеими фактическими зависимостями. Таким образом, ваш поставщик геокодирования будет осуществлять фактический вызов любому поставщику, которого вы используете, который может использовать запросы, которые могут быть ограничены. Также вы будете использовать настоящий Doctrine EntityManager, то есть все, что вы записываете в базу данных, действительно будет записано. Поэтому специально для базы данных вы должны создать отдельную тестовую базу данных и настроить ее в своем app/config/config_test.yaml.

...