【问题标题】:Mocking a service in unit test in Symfony 3.4在 Symfony 3.4 的单元测试中模拟服务
【发布时间】:2018-01-17 09:27:29
【问题描述】:

我有一个简单的 DefaultController 作为服务,其中 DI 是自动装配的。

class DefaultController extends BaseController
{
    private $logger;
    private $recordRepository;

    public function __construct(LoggerInterface $logger, RecordRepository $recordRepository)
    {
        $this->logger = $logger;
        $this->recordRepository = $recordRepository;
    }

    public function downloadAction($uuid)
    {
        $recordRepo = $this->recordRepository;

        $record = $recordRepo->findActive($uuid);

        $logger = $this->logger;

        if (!$record) {
            $logger->error('Record not found: '.$uuid);

            return $this->render('default/download_error.html.twig', [
                'error' => 'record_not_found'
            ]);
        }
    }
}

我编写了一个单元测试,它尝试调用此方法,同时还用模拟替换其中一个服务(记录器):

<?php
namespace Tests\AppBundle\Controller;

use Monolog\Logger;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class DefaultControllerTest extends WebTestCase {

    public function testDownloadAction()
    {
        $mock = $this->getMockBuilder(Logger::class)
            ->disableOriginalConstructor()
            ->getMock();

        $mock->expects($this->once())->method('error')
            ->with('Record not found: 1223');

        $client = static::createClient([]);

        $client->getContainer()->set('logger', $mock);

        $client->request('GET', '/download/12233');

        print $client->getResponse()->getContent();

        $this->assertEquals(200, $client->getResponse()->getStatusCode());
    }

}

问题是,当这个测试失败时(因为记录器错误和预期的字符串不匹配),PHPunit 消息被放入$client-&gt;getResponse 输出而不是被 CLI 捕获。

输出 CLI:

PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
F<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="robots" content="noindex,nofollow" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <title>    Expectation failed for method name is equal to &lt;string:error&gt; when invoked 1 time(s) Parameter 0 for invocation Monolog\Logger::error(&#039;Record not found: 12233&#039;, Array ()) does not match expected value. Failed asserting that two strings are equal. (500 Internal Server Error) </title> 

(further long webpage output removed here)

PHPUnit message:

There was 1 failure:

1) Tests\AppBundle\Controller\DefaultControllerTest::testDownloadAction
Failed asserting that 500 matches expected 200.

如果我想使用模拟对象,是否必须使用常规的 PHPUnit 案例?在这种情况下,我可能也应该重构控制器中的$this-&gt;render

【问题讨论】:

    标签: php symfony unit-testing phpunit


    【解决方案1】:

    1) 无需为控制器编写单元测试。如果有一些登录,则将其移至 Manager/Service/AnotherNameForLogicClass 并使用单元测试对其进行测试,而不是控制器 2) 控制器通过功能/集成测试进行测试,通常在此类测试中不需要模拟。

    有与此主题相关的不同文章。例如,来自 KNP:https://knpuniversity.com/screencast/symfony2-ep2/testing

    【讨论】:

    • 有道理,我现在正在混合不同的测试方法。我将使用一些 DB 固定装置并使其成为功能测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    相关资源
    最近更新 更多