Codeception / module-symfony

Codeception module for testing apps using Symfony framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't associate mock with symfony service

bogdan-dubyk opened this issue · comments

I have a lot of API calls and I want to mock API client in functional tests. Note: I run this process by Symfony command

But I'm still getting real API response

I have such a test case (simplified)

     $request = new Request(
                SymfonyRequest::METHOD_GET,
                'https://someurl.com/Apiv3/apps'
            );

        $apiClientMock = \Mockery::mock(HttpClientInterface::class);
        $apiClientMock
            ->shouldReceive('send')
            ->once()
            ->with(request)
            ->andReturn(new Response(HttpCode::OK, [], '{"data":"some data"}'));
        $I->replaceSymfonyServiceWithMock($apiClientMock);

        $I->runShellCommand('bin/console sync:apps');

and logic of replaceSymfonyServiceWithMockinside of functional helper

    /**
     * @param MockInterface $object
     * @param string|null $alias
     * @throws \Codeception\Exception\ModuleException
     */
    public function replaceSymfonyServiceWithMock(MockInterface $object, string $alias = null)
    {
        /** @var Symfony $symfony */
        $symfony = $this->getModule('Symfony');
        $testContainer = $symfony->grabService('test.service_container');

        if($alias !== null) {
            $alias = get_class($object);
        }

        $testContainer->set($alias, $object);
        $symfony->persistService($alias, false);
    }

Details

  • Codeception version: 2.4
  • PHP Version: 7.2.10
  • Operating System: MacOs
  • Installation type: Composer
  • Suite configuration:
actor: FunctionalTester
modules:
    enabled:
        - Symfony:
            app_path: src
            kernel_class: App\Kernel
            environment: test
        - Doctrine2:
            depends: Symfony
            cleanup: true
        - REST:
            depends: Symfony
            part: json
        - Cli
        - Mockery
        - \Helper\Functional

I have changed $I->replaceSymfonyServiceWithMock($apiClientMock); to $I->replaceSymfonyServiceWithMock($apiClientMock, HttpClientInterface::class); and I'm getting error

service is private, you cannot replace it.

But I'm trying to use https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing#comment-22223. is this test.service_container is useful only to get services from the container but not to set? If so, how can I associate service with the mocked instance?

@bogdan-dubyk Can you share the way you achieved this, or haven't you got a solution for this?

I'm also thinking about mocking services, and replace those services while running functional tests. But I'm starting to think my strategy of mocking third party API's is wrong.

I've got the same kind of situation. The application connects to several api's both third party and other api's we've developed, including Soap and REST.
To correctly test our application, I want to mock the results of those third party api's. Or the result of some application repositories which connect to those api's.

I thought of a way to replace those repositories with a Mocked version. But mocks are actually only available in unit tests, not functional tests.

I also stumbled upon the following extension https://github.com/mcustiel/codeception-http-mock which serves a webserver mocking the responses.

This issue is strongly related to #96, please check the closing comment.

It can be tricky to find the correct solution to a question that might need to be rephrased.