且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用PHPUnit在Symfony2中设置数据库重的单元测试?

更新时间:2023-11-19 17:18:22

tl; dr:


  • 当且仅当您想要执行整个功能测试路线时,我建议您查看 Sgoettschkes的答案

  • 如果要对应用程序进行单元测试,并且必须测试与数据库交互的代码,请直接读取或直接跳转到 symfony2 docs

  • 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.