there4 / slim-unit-testing-example Goto Github PK
View Code? Open in Web Editor NEWUnit Testing Slim - Example PHPUnit route testing and mocking with the Slim Framework dependency injection container.
License: MIT License
Unit Testing Slim - Example PHPUnit route testing and mocking with the Slim Framework dependency injection container.
License: MIT License
Hi,
Consider this route:
$app->get('/say-hello',function() use ($app){
$name = $app->request->params()['name'];
if (is_null($name)){
echo "Hello John Doe!";
} else {
echo "Hello ".$name."!";
}
Trying http://slim-api.com/say-hello
from a browser echos Hello John Doe!
Trying http://slim-api.com/say-hello?name=Craig
echos Hello Craig!
respectively.
So, here's the test for it:
public function testSayHello()
{
$parameters = array('name'=>'Craig Davis');
$this->get('/say-hello',$parameters);
$this->assertEquals(200, $this->response->status());
$this->assertSame("Hello Craig Davis!",$this->response->body());
}
This test fails:
oris@oris:~/slim-api$ phpunit tests/MyTest.php
PHPUnit 3.7.29 by Sebastian Bergmann.
Configuration read from /home/oris/slim-api/phpunit.xml
F
Time: 31 ms, Memory: 5.00Mb
There was 1 failure:
1) MyTest::testSayHello
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-Hello Craig Davis!
+Hello John Doe!
/home/oris/slim-api/tests/MyTest.php:31
/usr/share/php/PHPUnit/TextUI/Command.php:192
/usr/share/php/PHPUnit/TextUI/Command.php:130
FAILURES!
Tests: 1, Assertions: 2, Failures: 1.
Also, consider my addition to your tests/bootstrap.php
updating the request globals. (As written in issue #3 ) Maybe we need to improve it somehow?
Hi!
Consider the following route:
$app->put('/users/me',function() use ($app){
$app->response->headers->set('Content-Type', 'application/json');
$userData = $app->request()->put();
var_dump($userData);
});
This route basically accepts a PUT request and returns whatever variables came with it. When I test it with curl:
oris@oris:~/slim-api$ curl -i -H "Accept: application/json" -X PUT -d "hello=there" http://slim-api.com/users/me
HTTP/1.1 200 OK
Server: nginx/1.2.1
Date: Thu, 06 Feb 2014 09:53:11 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.4.6-1ubuntu1.5
Set-Cookie: PHPSESSID=2r6ta2fg6vdk7; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
array(1) {
["hello"]=>
string(5) "there"
}
This test:
public function testPutUsersMe()
{
$this->put('/users/me',"myKey=myValue");
$userResponse = $this->response->body();
var_dump($userResponse);
}
Causes this error:
oris@oris:~/slim-api$ phpunit
PHPUnit 3.7.29 by Sebastian Bergmann.
Configuration read from /home/oris/slim-api/phpunit.xml
..........E
Time: 119 ms, Memory: 7.75Mb
There was 1 error:
1) UserTest::testPutUsersMe
auto loader error when loading PHPUnit_Extensions_Database_TestCase on auto loader error when loading PHPUnit_Extensions_SeleniumTestCase on Illegal string offset 'slim.input'
/home/oris/slim-api/tests/bootstrap.php:96
/home/oris/slim-api/tests/UserTest.php:140
/usr/share/php/PHPUnit/TextUI/Command.php:192
/usr/share/php/PHPUnit/TextUI/Command.php:130
FAILURES!
Tests: 11, Assertions: 85, Errors: 1.
And this test:
public function testPutUsersMe()
{
$this->put('/users/me',array("myKey=myValue"));
$userResponse = $this->response->body();
var_dump($userResponse);
}
Causes this response which isn't quite right:
oris@oris:~/slim-api$ phpunit
PHPUnit 3.7.29 by Sebastian Bergmann.
Configuration read from /home/oris/slim-api/phpunit.xml
...........string(13) "array(0) {
}
"
Time: 120 ms, Memory: 7.75Mb
OK (11 tests, 85 assertions)
Where is the array content? Am I missing something obvious?
Thanks
The slim-test-helpers project has just been updated to use Slim v3. This project can now be updated to be show best practice testing for Slim v3.
Hi!
Consider the following code please:
public/index.php:
<?php
//tiny example:
require_once '../vendor/autoload.php';
session_start(); //starts a session so we could use $_SESSION
$app = new \Slim\Slim();
require_once '../app/app.php';
$app->run();
app/app.php:
<?php
$app->get("/weather", function() use ($app){
header('Content-type: application/json');
$myArray = array("weather outside"=>"cool and smooth");
//echo(json_encode($myArray));
exit(json_encode($myArray));
});
tests/bootstrap.php is taken from here: https://github.com/there4/slim-unit-testing-example/blob/master/tests/bootstrap.php and like so, phpunit.xml is taken from this repo unchanged except for minor colors="true"
addition.
tests/WeatherTest.php:
<?php
class WeatherTest extends Slim_Framework_TestCase
{
/**
* @runInSeparateProcess
*/
public function testWeather() //obvious test
{
$this->get('/weather');
$this->assertEquals(200, $this->response->status());
var_dump($this->response->body());
$this->assertEquals(json_encode('hellojjj'), $this->response->body());
}
}
Findings:
/weather
with the use of exit
on app/app.php returns the desired 'application/json' response type. Commenting the exit
from the route makes the response type text/html, albeit the header change on the route.* @runInSeparateProcess
annotation I get this error, which according to stackoverflow is known issue with phpunit:exception 'ErrorException' with message 'Cannot modify header information - headers already sent by (output started at /usr/share/php/PHPUnit/Util/Printer.php:173)' in /home/oris/php-example/app/app.php:10
If I do use it, with the exit
in the route, I get:
Configuration read from /home/oris/php-example/phpunit.xml
E
Time: 0 seconds, Memory: 2.75Mb
There was 1 error:
What am I missing? any recommendations (in addition to updating phpunit) would be greatly appreciated. Thanks.
Hackish include is not a best practice.
When I try to run multiple request in one test method, for example:
public function testRoutesIdCondition()
{
$this->get('/user/1');
$this->assertEquals(200, $this->response->status());
$this->get('/user/1a');
$this->assertEquals(404, $this->response->status());
$this->get('/category/1a');
$this->assertEquals(404, $this->response->status());
}
The following requests are unable to get the correct response
. (i.e., the remains requests will get a 200 instead of 404)
Maybe re-setup the mocking app before peforming every request will fix it. But I don't know if it's the best approach.
Firstly, thanks for the excellent guidance! I have been struggling with Slim integration testing for some time and this proved very useful indeed.
I did come across something that kept me occupied for a few hours - not a bug, but maybe worth mentioning.
I use Slim::getInstance()
in my controllers, because I use the Class:method
route syntax to keep things tidy. I know Slim can be injected in Slim3 using the home container, but I don't think so in Slim2.
When running a test class through phpunit, the first test succeeds but subsequent ones fail for no obvious reason. It turns out that Slim::getInstance()
will always return the instance from the first test, unless passed a name.
bootstrap:
public function getSlimInstance()
{
$app = new Slim(array(
'mode' => 'testing'
));
$app->setName('test');
return $app;
}
The first time new Slim()
is called the instance is stored in a protected static array inside Slim
against the key "default". setName
then adds another reference in the same array under the key "test".
Calling Slim::getInstance()
returns the object from default
which will always be the first one.
I solved it in a horrible way - tracked the application name in a static variable, so I can call Slim::getInstance(NAME)
Anyway - thought this might be useful to know!
Hi @craig-davis, I'm not able to access the Referer header within the app when testing:
Sample code:
$app->get('/issue', function () use ($app) {
$referer = $app->request->headers('referer');
$response = $referer ? $referer : 'Missing referer header';
$app->response->write($response);
});
Sample test:
public function testWithRefererWithPii()
{
$qs = array('');
$referer = array('Referer' => 'hello');
$this->client->get('/issue', $qs, $referer);
$this->assertEquals('hello', $this->client->response->body());
}
The phpunit results are:
There was 1 failure:
1) FilterPiiTest::testWithRefererWithPii
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'hello'
+'Missing referer header'
/vagrant/tests/FilterPiiTest.php:48
phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:186
phar:///usr/local/bin/phpunit/phpunit/TextUI/Command.php:138
FAILURES!
Tests: 2, Assertions: 1, Failures: 1.
Any ideas?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.