Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2823a40

Browse files
committed
Adding a database cookbook with the topics unit tests and config_test.yml covered
1 parent11b63e3 commit2823a40

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

‎cookbook/map.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
* :doc:`/cookbook/testing/http_authentication`
139139
* :doc:`/cookbook/testing/insulating_clients`
140140
* :doc:`/cookbook/testing/profiling`
141+
* :doc:`/cookbook/testing/database`
141142
* :doc:`/cookbook/testing/doctrine`
142143
* :doc:`/cookbook/testing/bootstrap`
143144
* (email) :doc:`/cookbook/email/testing`

‎cookbook/testing/database.rst

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
..index::
2+
single: Tests; Database
3+
4+
How to test code which interacts with the database
5+
==================================================
6+
7+
If your code interacts with the database, e.g. reads data from or stores data into
8+
it, you need to adjust your tests to take this into account. There are many ways
9+
how to deal with this. In a unit test, you can create a mock for a ``Repository``
10+
and use it to return expected objects. In a functional test, you may need to
11+
prepare a test database with predefined values, so a test always has the same data
12+
to work with.
13+
14+
Mocking the ``Repository`` in a Unit Test
15+
-----------------------------------------
16+
17+
If you want to test code which depends on a doctrine ``Repository`` in isolation, you
18+
need to mock the ``Repository``. Normally you get the ``Repository`` from the ``EntityManager``,
19+
so you would need to mock those as well. Suppose the class you want to test looks like this::
20+
21+
namespace Acme\DemoBundle\Salary;
22+
23+
use Doctrine\Common\Persistence\ObjectManager;
24+
25+
class SalaryCalculator
26+
{
27+
private $entityManager;
28+
29+
public function __construct(ObjectManager $entityManager)
30+
{
31+
$this->entityManager = $entityManager;
32+
}
33+
34+
public function calculateTotalSalary($id)
35+
{
36+
$employeeRepository = $this->entityManager->getRepository('AcmeDemoBundle::Employee');
37+
$employee = $userRepository->find($id);
38+
39+
return $employee->getSalary() + $employee->getBonus();
40+
}
41+
}
42+
43+
As the ``ObjectManager`` gets injected into the class through the constructor, it's
44+
easy to pass a mock object within a test::
45+
46+
use Acme\DemoBundle\Salary\SalaryCalculator;
47+
48+
class SalaryCalculatorTest extends \PHPUnit_Framework_TestCase
49+
{
50+
51+
public function testCalculateTotalSalary()
52+
{
53+
// First, mock the object to be used in the test
54+
$employee = $this->getMock('\Acme\DemoBundle\Entity\Employee');
55+
$employee->expects($this->once())
56+
->method('getSalary')
57+
->will($this->returnValue(1000));
58+
$employee->expects($this->once())
59+
->method('getBonus')
60+
->will($this->returnValue(1100));
61+
62+
// Now, mock tthe repository so it returns the mock of the employee
63+
$employeeRepository = $this->getMockBuilder('\Doctrine\ORM\EntityRepository')
64+
->disableOriginalConstructor()
65+
->getMock();
66+
$employeeRepository->expects($this->once())
67+
->method('__call')
68+
->will($this->returnValue($employee));
69+
70+
// Last, mock the EntityManager to return the mock of the repository
71+
$entityManager = $this->getMockBuilder('\Doctrine\ORM\EntityManager')
72+
->disableOriginalConstructor()
73+
->getMock();
74+
$entityManager->expects($this->once())
75+
->method('getRepository')
76+
->will($this->returnValue($employeeRepository));
77+
78+
$salaryCalculator = new SalaryCalculator($entityManager);
79+
$this->assertEquals(1100, $salaryCalculator->calculateTotalSalary(1));
80+
}
81+
}
82+
83+
We are building our mocks from the inside out, first creating the employee which
84+
gets returned by the ``Repository`` which itself gets returned by the ``EntityManager``.
85+
This way, no real class is involved in testing.
86+
87+
..note::
88+
89+
As a ``Repository`` doesn't have a ``find()`` method but uses the magic method
90+
``__call``, you cannot define a mock method on ``find()`` but must instead use
91+
``__call``. It's possible to implement the ``find()`` method in your ``Repository``
92+
and use it when mocking. In this case, make sure to mock your ``Repository``
93+
class instead of the generic ``EntityRepository``.
94+
95+
Changing database settings for functional tests
96+
-----------------------------------------------
97+
98+
If you have functional tests, you want them to interact with a real database.
99+
Most of the time you want to use a dedicated database connection to make sure
100+
not to overwrite data you entered when developing the application and also
101+
to be able to clear the database before every test.
102+
103+
To do this, you can specify the database configuration inside your ``app/config/config_test.yml``::
104+
105+
doctrine:
106+
dbal:
107+
host: localhost
108+
dbname: testdb
109+
user: testdb
110+
password: testdb
111+
112+
Make sure that your database runs on localhost and has the defined database and
113+
user credentials set up.
114+

‎cookbook/testing/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ Testing
77
http_authentication
88
insulating_clients
99
profiling
10+
database
1011
doctrine
1112
bootstrap

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp