PHPUnit -setUp() - does it run before and after each test case? - phpunit

I am still a bit confused with setup() in PHPUnit.
Does it run before and after each test case?
For intance, I want to clean up my article table before each test but I want to keep the test data that I already injected into the table. Because I only want to clean it until the next test.
My test,
namespace Test\Foo\Article;
use Test\SuiteTest;
use Foo\Article;
class ArticleTest extends SuiteTest
{
protected static $Article;
/**
* Call this template method before each test method is run.
*/
protected function setUp()
{
$this->truncateTables(
[
'article'
]
);
self::$Article = new Article(self::$PDO);
}
public function testFetchRow()
{
self::$Article->createRow(
[
':title' => 'Hello World',
':description' => 'Hello World',
':content' => 'Hello World'
]
);
$result = self::$Article->fetchRow(
[
':article_id' => self::$PDO->fetchLastInsertId()
]
);
$this->assertArrayHasKey('article_id', $result);
$expected = 12; // 12 keys associate with values in the array
$this->assertEquals($expected, count($result));
}
}
I check my article table, there is no test data anymore, it seems that setup() has cleaned it up. Is it how it should work?
What about the tearDown() - does it mean to run after the each test case?

setUp() runs before every single test method, tearDown() runs after each test method.
PHPUnit Manual - Chapter 4 Fixures:
Before a test method is run, a template method called setUp() is invoked
...
Once the test method has finished running, whether it succeeded or failed, another template method called tearDown() is invoked
See https://phpunit.de/manual/current/en/fixtures.html

Related

Silverstripe 3.7 Unit Tests - tearDownOnce() and setUpOnce() do not trigger

Silverstripe 3.7.6, PHP 7.3, PHPUnit 4.8
We have a bunch of existing unit tests that use SapphireTest->setUpOnce() and SapphireTest->tearDownOnce(). The latter is used to destroy test databases once complete. Which is how we found that these methods were not firing.
Simple test that simulates
<?php
class MyTest extends SapphireTest {
protected $usesDatabase = true;
public function setUp()
{
echo "setup \n";
parent::setUp();
}
public function tearDown()
{
echo "teardown \n";
parent::tearDown();
}
public function setUpOnce()
{
echo "setup once \n";
parent::setUpOnce();
}
public function tearDownOnce()
{
echo "teardown once \n";
parent::tearDownOnce();
}
function testSomething()
{
// My test
}
}
Output when test is run:
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
.setup teardown
Time: 6.38 seconds, Memory: 80.50MB
OK (1 test, 0 assertions)
Is there something that needs to be done in the test so these functions are fired at the start and end of the whole test class per docblock?
UPDATE:
See convo below. It was suggested that I use PHPUnit's setUpBeforeClass and tearDownAfterClass methods instead. These fired as expected. However they are static methods so I had no access to $this to use supporting SapphireTest or custom methods in the class. So I had to use these PHPUnit methods to instantiate an instance of the test class they sit in, then call my existing setUpOnce and tearDownOnce methods. I used late static binding's static() keyword here as I might move these calls into a parent class for my tests all to use. A bit hacky, but it seems to work.
Assuming my test code above, below is the addition to make:
public static function setUpBeforeClass() {
$object = new static();
$object->setUpOnce();
}
public static function tearDownAfterClass() {
$object = new static();
$object->tearDownOnce();
}

What should be really done in tearDown() in PhpUnit

Just assigning null to the obj is what done in tearDown().What all the entries created in db by other function while testing that will be deleted and for that we should write in tearDown() this was I thought.
protected function setUp()
{
$this->XSCCategoryModelObj = new XSCCategoryModel();
}
protected function tearDown()
{
$this->XSCCategoryModelObj =null;
}
I believe that this section from documentation answers on your question. Also, this part with explanation can help:
The setUp() and tearDown() template methods are run once for each test method (and on fresh instances) of the test case class.
In addition, the setUpBeforeClass() and tearDownAfterClass() template methods are called before the first test of the test case class is run and after the last test of the test case class is run, respectively.

Suppress symfony 4 response body in phpunit test

I am migrating a Silex app to Symfony Flex and everything is working so far, except that when I run the phpunit tests I get the response body output into the phpunit output.
ie.
> bin/phpunit
#!/usr/bin/env php
PHPUnit 6.5.13 by Sebastian Bergmann and contributors.
Testing unit
.......<http://data.nobelprize.org/resource/laureate/914> a <http://data.nobelprize.org/terms/Laureate> , <http://xmlns.com/foaf/0.1/Person> ;
<http://www.w3.org/2000/01/rdf-schema#label> "Malala Yousafzai" ;
<http://data.nobelprize.org/terms/laureateAward> <http://data.nobelprize.org/resource/laureateaward/974> ;
<http://data.nobelprize.org/terms/nobelPrize> <http://data.nobelprize.org/resource/nobelprize/Peace/2014> ;
the entire RDF document then
. 8 / 8 (100%)
Time: 1.07 seconds, Memory: 14.00MB
OK (8 tests, 71 assertions)
Generating code coverage report in Clover XML format ... done
So it is working fine, but I can't figure out how to disable this output?
The request is simply
$this->client->request('GET', "/nobel_914.ttl", [], [], ['HTTP_ACCEPT' => $request_mime]);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), "GET should be allowed.");
$response = $this->client->getResponse();
$charset = $response->getCharset();
etc.
and the client is setup in a base class like this
class MyAppTestBase extends WebTestCase
{
/**
* #var \Symfony\Component\BrowserKit\Client
*/
protected $client;
/**
* {#inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->client = static::createClient();
$this->client->catchExceptions(false);
}
I'm sure I'm missing something obvious but this is new to me. I am running in the 'test' environment and with 'debug' == false.
Any help appreciated.
So this was probably a problem all along but just started being exposed in the switch from Silex to Symfony Flex.
We were streaming responses via
$filename = $this->path;
$stream = function () use ($filename) {
readfile($filename);
};
return new StreamedResponse($stream, 200, $res->headers->all());
and the readfile was throwing the content to the output buffer. Switching the readfile to file_get_contents resolved this
$filename = $this->path;
$stream = function () use ($filename) {
file_get_contents($filename);
};
return new StreamedResponse($stream, 200, $res->headers->all());

Passing data provider to setUp() in PHPUnit

I'm currently trying to pass data from my data provider to the setUp()-method in PHPUnit.
Background: I am using PHPUnit for running frontend-tests in different browsers. The browser should be defined inside the data provider and needs to be known by the setUp()-method.
I understand, that a data provider initially is executed before the setUp()-method (as setUpBeforeClass()) is called. Therefore setUp()-data can not be passed to a data provider. But it should work the other way round, shouldn't it?
Does PHPUnit generate its own temporarily testclasses with data from the data provider "integrated"?
Of course: a workaround could be, to read the XML-file in the setUp()-method again. But that's the last option, I'd consider...
EDIT: Provided a small snippet:
part of dataProvider():
public function dataProvider()
{
$this->xmlCnf = $data['config'];
var_dump($this->xmlCnf); // array with config is exposed
// [...]
}
And the setUp()-method:
protected function setUp()
{
var_dump($this->xmlCnf); // NULL
//[...]
}
In case this is useful to anyone:
The following code should work:
public function dataProvider()
{
return [ [ /* dataset 1 */] , ... ]
}
protected setUp() {
parent::setUp();
$arguments = $this->getProvidedData();
// $arguments should match the provided arguments for this test case
}
/**
* #dataProvider dataProvider
*/
public function testCase(...$arguments) {
}
The getProvidedData method seems to have been available since PHPUnit 5.6 (which was either shortly before or after this question was originally asked)
we can make the xmlCnf to static
private static $xmlCnf;
public function provider(){
self::$xmlCnf = 'hello';
var_dump(self::$xmlCnf); //hello
return [...];
}
public function setUp() {
var_dump(self::$xmlCnf); //hello
parent::setUp();
}

symfony test database insert

I have a functional test that creates and persists some things in the database and I want to test that the correct number of items was inserted (there is a scenario where it currently inserts two instead of one).
In the controller everything seems to work and if I use the code below (in the controller) to debug it, I get the expected (wrong) value of "2":
$em = $this->getDoctrine()->getManager();
$fooRepo = $em->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // Gives a result of 2
However, if I try something similar from within my Test class I get zero...
/**
* {#inheritDoc}
*/
protected function setUp()
{
static::$kernel = static::createKernel();
static::$kernel->boot();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager()
;
$this->em->getConnection()->beginTransaction();
}
/**
* {#inheritDoc}
*/
protected function tearDown()
{
parent::tearDown();
$this->em->getConnection()->rollback();
$this->em->close();
}
public function testFooForm()
{
// ... do some testing
$fooRepo = $this->em->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // gives a result of ZERO
// ... more happens later
}
Is it getting a different entity manager or something like that? Should I be using some other method to get hold of the correct EM so I can then view the same data that the app is running from?
Everything's running inside a transaction (which is rolled back when the test client is destroyed), but that happens after the snippet shown above.
Ah... solved my own problem. I think I was getting the wrong EntityManager. I fixed it by getting the EntityManager via the client's container instead of the kernel's one:
public function testFooForm()
{
// ... do some testing
$clientEm = $client->getContainer()->get('doctrine.orm.entity_manager');
$fooRepo = $clientEm->getRepository('CompanyProjectBundle:Foo');
$foos = $fooRepo->retrieveByBar(3);
echo count($foos); // gives the correct result of 2
// ... more happens later
}

Resources