如何使用PHPUnit在Symfony2中设置数据库重的单元测试? [英] How to set up database-heavy unit tests in Symfony2 using PHPUnit?

查看:75
本文介绍了如何使用PHPUnit在Symfony2中设置数据库重的单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是测试世界的新手,我想确保我在正确的轨道上。

I am quite new to the world of testing and I want to make sure I am on the right track.

我正在尝试在 symfony2 项目使用 phpunit

I am trying to setup unit tests in a symfony2 project using phpunit.

PHPUnit 正在工作,简单的默认控制器测试工作正常。 (但这不是关于功能测试,而是单位测试我的应用程序。)

PHPUnit is working and the simple default controller tests work fine. (Yet this is not about functional testing but unit testing my application.)

我的项目很大程度上依赖于数据库交互,据我所知,从 phpunit的文档,我应该设置一个基于 \的类PHPUnit_Extensions_Database_TestCase ,然后为我的数据库创建工具并从那里工作。

My project relies heavily on database interactions though, and as far as I understand from phpunit's documentation, I should set up a class based on \PHPUnit_Extensions_Database_TestCase, then create fixtures for my db and work from there.

然而,symfony2 仅提供 WebTestCase 类,只从 \PHPUnit_Framework_TestCase 开始使用。

Yet, symfony2 only offers a WebTestCase class which only extends from \PHPUnit_Framework_TestCase out of the box.

所以我可以假设我应该创建自己的 DataBaseTestCase ,它们主要复制 WebTestCase ,只有区别是它从 \PHPUnit_Extensions_Database_TestCase 中扩展并实现其所有抽象方法?

So am I right to assume that I should create my own DataBaseTestCase which mostly copies WebTestCase, only difference being that it extends from \PHPUnit_Extensions_Database_TestCase and implements all its abstract methods?

还是有另一个内置symfony2 推荐的工作流程以数据库为中心的测试?

Or is there another "built-in" recommended workflow for symfony2 concerning database-centric tests?

由于我想确保我的模型存储和检索正确的数据,我不想最终测试

As I want to make sure that my models store and retrieve the right data, I do not want to end up testing the specifics of doctrine by accident.

推荐答案

tl; dr:

  • If and only if you want to go the whole functional test route, then I recommend looking up Sgoettschkes's answer.
  • If you want to unit test your application and have to test code that interacts with the database, either read on or jump directly to symfony2 docs



我的原始问题中有一些方面表明我对于单元测试和功能测试之间的差异的理解是缺乏的。 (正如我所写的,我想单位测试应用程序,但同时也在谈论控制器测试;这些是通过定义的功能测试)。


There were certain aspects in my original question that make it clear that my understanding of the differences between unit testing and functional tests was lacking. (As I have written I want to unit test the application, yet was also talking about Controller test at the same time; and those are functional test by defintion).

单位测试只对服务有意义,而不是存储库。这些服务可以使用实体管理器的嘲讽。

Unit testing only makes sense for services and not for repositories. And those services can use mocks of the entity manager.

我的应用程序的实际用例实际上很好地反映在如何测试与数据库交互的代码。他们为服务测试提供了这个例子:

My actual use case for my application was in fact pretty well reflected on the symfony2 docs on how to test code that interacts with the databse. They provide this example for a service test:

服务类:

use Doctrine\Common\Persistence\ObjectManager;

class SalaryCalculator
{
    private $entityManager;

    public function __construct(ObjectManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function calculateTotalSalary($id)
    {
        $employeeRepository = $this->entityManager
            ->getRepository('AppBundle:Employee');
        $employee = $employeeRepository->find($id);

        return $employee->getSalary() + $employee->getBonus();
    }
}

服务测试类:

namespace Tests\AppBundle\Salary;

use AppBundle\Salary\SalaryCalculator;
use AppBundle\Entity\Employee;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ObjectManager;

class SalaryCalculatorTest extends \PHPUnit_Framework_TestCase
{
    public function testCalculateTotalSalary()
    {
        // First, mock the object to be used in the test
        $employee = $this->getMock(Employee::class);
        $employee->expects($this->once())
            ->method('getSalary')
            ->will($this->returnValue(1000));
        $employee->expects($this->once())
            ->method('getBonus')
            ->will($this->returnValue(1100));

        // Now, mock the repository so it returns the mock of the employee
        $employeeRepository = $this
            ->getMockBuilder(EntityRepository::class)
            ->disableOriginalConstructor()
            ->getMock();
        $employeeRepository->expects($this->once())
            ->method('find')
            ->will($this->returnValue($employee));

        // Last, mock the EntityManager to return the mock of the repository
        $entityManager = $this
            ->getMockBuilder(ObjectManager::class)
            ->disableOriginalConstructor()
            ->getMock();
        $entityManager->expects($this->once())
            ->method('getRepository')
            ->will($this->returnValue($employeeRepository));

        $salaryCalculator = new SalaryCalculator($entityManager);
        $this->assertEquals(2100, $salaryCalculator->calculateTotalSalary(1));
    }
}

只有这种测试才需要测试数据库(痛苦的)嘲笑。

No test database required for those kind of test, only (painful) mocking.

由于重要的是测试业务逻辑,而不是持久层。

As it is important to test the business logic, not the persistence layer.

只有在功能测试中,有自己的测试数据库才能建立和拆除,最重要的问题应该是:

Only for functional test it makes sense to have its own test database that one should build and tear down afterwards, and the big question should be:

功能测试什么时候有意义?

When do functional test make sense?

我曾经认为,测试所有的东西是正确的答案;但是,在使用很多传统软件本身几乎没有被测试驱动开发之后,我已经变得更加懒惰实用,并且考虑某些功能,直到证明是错误的。

I used to think that test all the things is the right answer; yet after working with lots of legacy software that in itself was barely test-driven developped I have become a bit more lazypragmatic and consider certain functionality as working until proven otherwise by a bug.

假设我有一个解析XML的应用程序,从中创建一个对象,并将这些对象存储到数据库中。如果将对象存储到数据库中的逻辑已知可以工作(如:公司需要数据,并且至今尚未破裂),即使该逻辑是一大堆垃圾,也没有 imminent 需要测试。所有我需要确保我的XML解析器提取正确的数据。我可以从经验中推断出正确的数据将被存储。

Assume I have an application that parses an XML, creates an object out of it, and stores those objects into a database. If the logic that stores the objects to the database is known to work (as in: the company requires the data and is, as of yet, not broke), and even if that logic is a big ugly pile of crap, there is no imminent need to test that. As all I need to make sure that my XML parser extracts the right data. I can infer from experience that the right data will be stored.

有些功能测试很重要的场合,比如说是写一个网上商店。在这里,购买的项目将被存储到数据库中,这将是至关重要的,这里使用整个测试数据库进行功能测试是绝对有意义的。

There are scenarios where functional test are quite important, i.e. if one were to write an online shop. There it would be business critical that bought items get stored into the database and here functional test with the whole test databse makes absolute sense.

这篇关于如何使用PHPUnit在Symfony2中设置数据库重的单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆