testing error_log with PHPUnit - php

I have this function I want to test looking like this:
class Logger {
function error($msg){
if (is_string($msg)){
error_log($msg);
die($msg);
} elseif (is_object($msg)){
error_log($msg.' '.$msg->getTraceAsString());
die('exception');
} else {
var_dump($msg);
die('error');
}
}
I want to test this function without logging the $msg. Is there a way to determine if error_log works without logging? I tried using setExpectedException but I wasn't able to catch the error and it kept logging.

The obvious answer is a simple alias/proxy-function that itself called error_log in the Logger class (which can be easily mocked, and checked to see what is set to it),
To actually test the native error_log function however (without a proxy in the original class), can be done with namespaces. The test would end up defined to be the same namespace as the original code, and then after the test class, add a function - in this case error_log() - but that function is also defined in the namespace - and so would be run in preference to the root-namespace-equivalent from the native functions.
Unfortunately, you can't do the same overriding with die (or its alias, exit). They are 'language constructs', and cannot be overridden like error_log can.
<?php
namespace abc;
use abc\Logger;
class ThreeTest extends \PHPUnit_Framework_TestCase
{
public function setUp() { $this->l = new Logger(); }
// test code to exercise 'abc\Logger'
}
// Now define a function, still inside the namespace '\abc'.
public function error_log($msg)
{
// this will be called from abc\Logger::error
// instead of the native error_log() function
echo "ERR: $msg, ";
}

you can use a function-mocking framework like php-mock (there are others as well) to mock the call to error_log (and check whether it is called with your expected parameters).
Unfortunately you will not be able to use that for the die-construct as that is not a normal function but anlanguage construct.
I'd replace the die() with a 'throw new \Exception()' (or any other appropriate exception) as you can then
test for the thrown exception and
can decide in your programming whether execution shall be stopped on calling the logger or whether you want to go on by wrapping the call into a try/catch
But I'd also ask myself whether the execution has to stop when calling a logger

Capturing error_log() output in a variable
If you want to redirect the error_log() output in a way that lets you inspect it with PHPUnit assertions, the following code works for me:
$errorLogTmpfile = tmpfile();
$errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']);
error_log("Test for this message");
ini_set('error_log', $errorLogLocationBackup);
$result = stream_get_contents($errorLogTmpfile);
// Result: [11-May-2022 22:27:08 UTC] Test for this message
As you can see, it uses a temporary file to collect the output, then grabs the content into a variable and resets the error_log config.
Re-usable methods
Personally, I've organized this into a pair of methods that I inject into the PHPUnit object with a trait so I can re-use them.
Of course the code below won't work out of the box, but it serves to demonstrate how you can make this system re-usable:
trait WithWPTestCaseGeneralTools {
var $gvErrorLogLocationBackup = "";
var $gvErrorLogTmpfile = "";
public function gvErrorLogStartListening() {
$this->gvErrorLogTmpfile = tmpfile();
$streamUri = stream_get_meta_data($this->gvErrorLogTmpfile)['uri'];
$this->gvErrorLogLocationBackup = ini_set('error_log', $streamUri);
}
public function gvErrorLogGetContents() {
ini_set('error_log', $this->gvErrorLogLocationBackup);
return stream_get_contents($this->gvErrorLogTmpfile);
}
}
You could of course achieve the same things with a couple of functions that use globals, I'll leave that to you if it's what you need!

Related

How to return false from a PHP script from inside a class/function?

How can I make the main PHP script return false from inside a class or a function?
Why: this is because of the built-in webserver:
If a PHP file is given on the command line when the web server is started it is treated as a "router" script. The script is run at the start of each HTTP request. If this script returns FALSE, then the requested resource is returned as-is.
from the documentation about the PHP Built-in webserver
In other words, you return false in your router script so that the built-in webserver can serve static files. Example from the documentation:
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // serve the requested resource as-is.
} else {
echo "<p>Welcome</p>";
}
The thing is that I'm trying to add that behavior to a web framework: I don't want to write that into index.php. I'd rather encapsulate that logic into a class (middleware) that will halt the script's execution if php_sapi_name() == 'cli-server' and a static asset is asked.
However, I don't know how I can make the whole PHP script return false from a class or a function, since obviously return false will return from the current method/function/file and not from the main file.
Is there a way to achieve the same behavior with exit() for example? I realize I don't even know what return false in the main file actually means (is that a specific exit code?).
You should have the router invoke the class method, and then, if the method returns false, you return false from your router file.
Of course it can turn into a headache. There are basically only two methods to achieve what you want to achieve.
There is a faster way though, you can abuse exceptions and create a specialized exception for the case:
StaticFileException.php
<?php
class StaticFileException extends Exception {}
router.php
<?php
try {
$c = new Controller();
return $c->handleRequest();
} catch (StaticFileException $e) {
return false;
}
Once you have this kind of code in place, just throw new StaticFileException and you're done.
If the method in your class handles static assets by using exit then the solution can be as simple as replacing exit with return false and having the caller of that method simply return the method in the global scope as well.
So if your class looks something like this...
class Router
{
public function handleRequest($uri)
{
if (is_file($this->docRoot . $uri->path)) {
exit; // static file found
} else {
// handle as normal route
}
}
}
Just replace exit there with return false ...
return false; // static file found
Then if your index.php works something like this...
$router = new Router($docRoot);
$router->handleRequest($_SERVER['REQUEST_URI']);
Simply add a return infront of the handleRequest method like so....
return $router->handleRequest($_SERVER['REQUEST_URI']);
This should have minimal side-effects on your framework design and as you can see requires very little code and refactoring because returning from the script's global scope only has a single side-effect in PHP (in that it returns the value to calling script i.e. if you used include/require as an expression in an assignment). In your case if index.php is the calling script then you have nothing to worry about here just by adding return infront of that method.
Of course, once you return the rest of the script will not continue so make sure it is the last statement in your index.php. You can even just assign the return value to a temporary value and return later if you needed for logic....
$router = new Router($docRoot);
if ($router->handleRequest($_SERVER['REQUEST_URI'])) {
/* if you need to do anything else here ... */
} else {
return false; // otherwise you can return false for static here
}
In general I would say that calling exit from inside of a function/method is almost never desirable. It makes your class harder to test and debug and really has no upside from the alternatives like throwing an exception, or just returning from the method, and letting the caller handle the failure scenarios gracefully.
Isn't possible to play with register_shutdown_function or with auto_append_file setting to deal with that? Not really nice but maybe that can do the job.

Call exit function from child class in PHP

I have a PHP class where I have to invoke PHP header function to show a webpage. As pointed out from this post, header should be followed by exit callback. Since this situation is very common in my classes, I've defined a method in parent class:
class ParentClass
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
I would like to invoke this method from children classes:
class ChildClass extends ParentClass
{
public function someFunc()
{
$this->header($some_url);
}
}
PHP documentation says that exit terminates the current script. My question is: does the exit function terminate child script even if it is contained in parent class?
EDIT
In my specific situation, I am using a MVC design pattern and ChildClass is a controller. Inside it, sometimes I need to show a view, sometimes I need to redirect to another url. Let me explain it with a practical example.
Suppose to have a website with a login section. When login page is displayed to users (login data not submitted), login controller should show login view. This view contains a form with an action like action="login.html". When data is submitted, login controller is invoked and checks login data: if login is successful, user is redirected to his admin section.
class UsersController extends BaseController
{
public function login()
{
try
{
if(isset($_POST['submit']))
{
// check login data, throw exception in case of error
// if success, redirect to admin section
$this->header('admin.html');
}
else
{
// show login view
}
}
catch(Exception $e)
{
// show login view (with error)
}
}
}
class BaseController
{
protected function header($url)
{
header('Location:'.$url);
exit;
}
}
Since this situation is quite common in my controllers, I've preferred to define a header method in BaseController instead of typing everytime
header('Location:someURL.html');
exit;
In my OP, I only wanted to be sure that $this->header('admin.html'); callback would terminate current login method, even if it is defined in BaseController script.
Hope it's a little clearer now.
As already descripted in the comment, exit will terminate everything, i.e. the webpage immediately stops executing, including clean up functions and finally blocks.
So, you should consider using exit very carefully because many things might happen: data doesn't get written to the database when you're not using auto-commit (unless you commit the data before calling exit). Auto-commit is not enabled by default in PHP's MySQL module (as far as I know).
Here is an example:
class B extends A {
public function someFunc() {
# you might wanna use partent instead as
# pointed out by Ding in the comments, but
# maybe someFunc does more that just doing
# the redirect.
$this->header("http://google.com");
}
}
try {
print("Ok...");
$obj = new B();
$obj->someFunc();
print("Nahh..."); # doesn't get called/
} finally {
print("Cleaning up."); # doesn't get called, either.
}
Instead of calling the exit method, you should rather implement a clear MVC design pattern. Here is a very quick example:
<?php
class Response {
# use private here and use appropriate
# getters and setters.
public $status_code = 200;
public $content = "";
public $headers = array();
}
class HomeView extends View {
# called when a get request is made.
public function get() {
$response = new Response();
$response->content = "Hello world."
}
}
class RedirectionView {
public function get() {
$response = new Response();
$response->status_code = 301; # use 302 if moved only temporarily.
$response->headers["Location"] = "http://google.com";
}
}
function processRequest() {
# load appropriate view programatically
$view = new RedirectionView();
$response = $view->get();
http_response_code($response->status_code);
foreach ($response->headers as $headerName => $headerValue) {
header(sprintf("%s: %s", $headerName, $headerValue));
}
print($view->content)
}
?>
Note that this is not really a MVC design pattern (the model is missing and, well, it's not clear what the controller, however, that's what django (a Pyhton framework) uses, too). You might wanna check out PHP MVC frameworks (a quick google search will do the trick) or implement your own (my example might be a good start).
Edit 1:
Using exit is probably ok (but I wouldn't use it because I believe it is bad practice). If you're able to edit the design approach you're using, I'd make your View BaseClass get/post method (or whatever you're the method that returns response object. Note: if you're using prints to show the response to the user, try to add a Response which contains all the data you're request needs to show. This is better than having prints (or echos) everywhere in your code).
Using the response object, your code would then be able to either just set the location header (if it's a redirect) or show the message. So you don't need to "kill" any part of the webpage and it will terminal when the execution ends. But again: you're probably good to go with an exit call in your method (unless you're encountering any issues with your code (database transactions that aren't committed, statistic data that is not updated (because its after the exit statement). Exit will simply terminate your script completely.

Is it possible to overwrite a function in PHP

Can you declare a function like this...
function ihatefooexamples(){
return "boo-foo!";
};
And then redeclare it somewhat like this...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
Is it possible to overwrite a function that way?
Any way?
Edit
To address comments that this answer doesn't directly address the
original question. If you got here from a Google Search, start here
There is a function available called override_function that actually fits the bill. However, given that this function is part of The Advanced PHP Debugger extension, it's hard to make an argument that override_function() is intended for production use. Therefore, I would say "No", it is not possible to overwrite a function with the intent that the original questioner had in mind.
Original Answer
This is where you should take advantage of OOP, specifically polymorphism.
interface Fooable
{
public function ihatefooexamples();
}
class Foo implements Fooable
{
public function ihatefooexamples()
{
return "boo-foo!";
}
}
class FooBar implements Fooable
{
public function ihatefooexamples()
{
return "really boo-foo";
}
}
$foo = new Foo();
if (10 == $_GET['foolevel']) {
$foo = new FooBar();
}
echo $foo->ihatefooexamples();
Monkey patch in namespace php >= 5.3
A less evasive method than modifying the interpreter is the monkey patch.
Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own.
Ninja skills
Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces.
Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. As this topic, fallback to global functions, aims to explain.
If you don't provide a namespace when calling a function, PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. For our example if you are calling print_r(); from namespace My\Awesome\Namespace; What PHP does is to first look for a function called My\Awesome\Namespace\print_r(); then My\Awesome\print_r(); then My\print_r(); until it finds the PHP built in function in the global namespace \print_r();.
You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists.
Expect a fatal error to the likes of:
Fatal error: Cannot redeclare print_r()
But nothing stops you, however, from doing just that within the scope of a namespace.
Patching the monkey
Say you have a script using several print_r(); calls.
Example:
<?php
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
But you later change your mind and you want the output wrapped in <pre></pre> tags instead. Ever happened to you?
Before you go and change every call to print_r(); consider monkey patching instead.
Example:
<?php
namespace MyNamespace {
function print_r($object)
{
echo "<pre>", \print_r($object, true), "</pre>";
}
print_r($some_object);
// do some stuff
print_r($another_object);
// do some other stuff
print_r($data_object);
// do more stuff
print_r($debug_object);
}
Your script will now be using MyNamespace\print_r(); instead of the global \print_r();
Works great for mocking unit tests.
nJoy!
Have a look at override_function to override the functions.
override_function — Overrides built-in
functions
Example:
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
short answer is no, you can't overwrite a function once its in the PHP function scope.
your best of using anonymous functions like so
$ihatefooexamples = function()
{
return "boo-foo!";
}
//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
return "really boo-foo";
}
http://php.net/manual/en/functions.anonymous.php
You cannot redeclare any functions in PHP. You can, however, override them. Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want.
So, keep in mind that when you override a function, you lose it. You may want to consider keeping it, but in a different name. Just saying.
Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function.
Example:
rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
I would include all functions of one case in an include file, and the others in another include.
For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really }
It helps the readability / maintenance of your program, having all functions of the same kind in the same inc.
Then at the top of your main module
if ($_GET['foolevel'] == 10) {
include "really.inc";
}
else {
include "simple.inc";
}
You could use the PECL extension
runkit_function_redefine — Replace a function definition with a new implementation
but that is bad practise in my opinion. You are using functions, but check out the Decorator design pattern. Can borrow the basic idea from it.
No this will be a problem.
PHP Variable Functions
Depending on situation where you need this, maybe you can use anonymous functions like this:
$greet = function($name)
{
echo('Hello ' . $name);
};
$greet('World');
...then you can set new function to the given variable any time
A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file):
Main File:
<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>
Include File A:
<?php
if (!#$Override) {
function F1 () {echo "This is F1() in A";}
}
?>
Include File B:
<?php
function F1 () {echo "This is F1() in B";}
?>
Browsing to the main file displays "This is F1() in B".

How do you use PHPUnit to test a function if that function is supposed to kill PHP?

Essentially I have a method of a class called killProgram, which is intended to send a hTTP redirect and then kill PHP.
How am I supposed to test this? When I run phpunit it doesn't return anything for that test, and closes completely.
Right now I'm considering having the killProgram function throw an exception which shouldn't get handled, which would allow me to assert that an exception was thrown.
Is there a better way?
It's obviously an old question but my suggestion would be to move the code that die()'s into a separate method that you can then mock.
As an example, instead of having this:
class SomeClass
{
public function do()
{
exit(1);
// or
die('Message');
}
}
do this:
class SomeClass
{
public function do()
{
$this->terminate(123);
// or
$this->terminate('Message');
}
protected function terminate($code = 0)
{
exit($code);
}
// or
protected function terminate($message = '')
{
die($message);
}
}
That way you can easily mock the terminate method and you don't have to worry about the script terminating without you being able to catch it.
Your test would look something like this:
class SomeClassTest extends \PHPUnit_Framework_TestCase
{
/**
* #expectedExceptionCode 123
*/
public function testDoFail()
{
$mock = $this->getMock('SomeClass');
$mock->expects($this->any())
->method('terminate')
->will($this->returnCallback(function($code) {
throw new \Exception($code);
}));
// run to fail
$mock->do();
}
}
I haven't tested the code but should be pretty close to a working state.
As every tests are run by the same PHPUnit process, if you use exit/die in your PHP code, you will kill everything -- as you noticed ^^
So, you have to find another solution, yes -- like returning instead of dying ; or throwing an exception (you can test if some tested code has thrown an expected exception).
Maybe PHPUnit 3.4 and it's --process-isolation switch (see Optionally execute each test using a separate PHP process) might help (by not having everything dying), but you still wouldn't be able to get the result of the test, if PHPUnit doesn't get the control back.
I've had this problem a couple of times ; solved it by returning instead of dying -- even returning several times, if needed, to go back "high enough" in the call stack ^^
In the end, I suppose I don't have any "die" anymore in my application... It's probably better, when thinking about MVC, btw.
There's no need to change the code just to be able to test it, you can simply use set_exit_overload() (provided by test_helpers from same author as PHPUnit).
I realise you've already accepted an answer for this and it's an old question, but I figure this might be useful for someone, so here goes:
Instead of using die(), you could use throw new RuntimeException() (or an exception class of your own), which will also halt program execution (albeit in a different fashion) and use PHPUnit's setExpectedException() to catch it. If you want your script to die() when that exception is encountered, printing absolutely nothing up at level of the user, take a look at set_exception_handler().
Specifically, I'm thinking of a scenario in which you'd place the set_exception_handler()-call into a bootstrap file that the tests don't use, so the handler won't fire there regardless of scenario, so nothing interferes with PHPUnit's native exception handling.
This relates to set of issues I've been having getting some legacy code to pass a test. So I've come up with a Testable class like this...
class Testable {
static function exitphp() {
if (defined('UNIT_TESTING')) {
throw new TestingPhpExitException();
} else {
exit();
}
}
}
Now I simply replace calls to exit() with Testable::exitphp().
If it's under test I just define UNIT_TESTING, in production I don't. Seems like a simple Mock.
You can kill the script or throw an exception, depending on the value of an environmental variable...
So you kill in production or throw an exception in test environment.
Any call to die or exit, Kills the whole process...
This was supposed to be a comment but I can't comment with the level of my reputation points.

test the return value of a method that triggers an error with PHPUnit

This question is specific to using PHPUnit.
PHPUnit automatically converts php errors to exceptions. Is there a way to test the return value of a method that happens to trigger a php error (either built-in errors or user generated errors via trigger_error)?
Example of code to test:
function load_file ($file)
{
if (! file_exists($file)) {
trigger_error("file {$file} does not exist", E_USER_WARNING);
return false;
}
return file_get_contents($file);
}
This is the type of test I want to write:
public function testLoadFile ()
{
$this->assertFalse(load_file('/some/non-existent/file'));
}
The problem I am having is that the triggered error causes my unit test to fail (as it should). But if I try to catch it, or set an expected exception any code that after the error is triggered never executes so I have no way of testing the return value of the method.
This example doesn't work:
public function testLoadFile ()
{
$this->setExpectedException('Exception');
$result = load_file('/some/non-existent/file');
// code after this point never gets executed
$this->assertFalse($result);
}
Any ideas how I could achieve this?
There is no way to do this within one unit test. It is possible if you break up testing the return value, and the notice into two different tests.
PHPUnit's error handler catches PHP errors and notices and converts them into Exceptions--which by definition stops program execution. The function you are testing never returns at all. You can, however, temporarily disable the conversion of errors into exceptions, even at runtime.
This is probably easier with an example, so, here's what the two tests should look like:
public function testLoadFileTriggersErrorWhenFileNotFound()
{
$this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
$result = load_file('/some/non-existent/file');
}
public function testLoadFileRetunsFalseWhenFileNotFound()
{
PHPUnit_Framework_Error_Warning::$enabled = FALSE;
$result = load_file('/some/non-existent/file');
$this->assertFalse($result);
}
This also has the added bonus of making your tests clearer, cleaner and self documenting.
Re: Comment:
That's a great question, and I had no idea until I ran a couple of tests. It looks as if it will not restore the default/original value, at least as of PHPUnit 3.3.17 (the current stable release right now).
So, I would actually amend the above to look like so:
public function testLoadFileRetunsFalseWhenFileNotFound()
{
$warningEnabledOrig = PHPUnit_Framework_Error_Warning::$enabled;
PHPUnit_Framework_Error_Warning::$enabled = false;
$result = load_file('/some/non-existent/file');
$this->assertFalse($result);
PHPUnit_Framework_Error_Warning::$enabled = $warningEnabledOrig;
}
Re: Second Comment:
That's not completely true. I'm looking at PHPUnit's error handler, and it works as follows:
If it is an E_WARNING, use PHPUnit_Framework_Error_Warning as an exception class.
If it is an E_NOTICE or E_STRICT error, use PHPUnit_Framework_Error_Notice
Else, use PHPUnit_Framework_Error as the exception class.
So, yes, errors of the E_USER_* are not turned into PHPUnit's *_Warning or *_Notice class, they are still transformed into a generic PHPUnit_Framework_Error exception.
Further Thoughts
While it depends exactly on how the function is used, I'd probably switch to throwing an actual exception instead of triggering an error, if it were me. Yes, this would change the logic flow of the method, and the code that uses the method... right now the execution does not stop when it cannot read a file. But that's up to you to decide whether the requested file not existing is truly exceptional behaviour. I tend to use exceptions way more than errors/warnings/notices, because they are easier to handle, test and work into your application flow. I usually reserve the notices for things like depreciated method calls, etc.
Use a phpunit.xml configuration file and disable the notice/warning/error to Exception conversion. More details in the manual. It's basically something like this:
<phpunit convertErrorsToExceptions="false"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false">
</phpunit>
Instead of expecting a generic "Exception", what about expecting a "PHPUnit_Framework_Error" ?
Something like this might do :
/**
* #expectedException PHPUnit_Framework_Error
*/
public function testFailingInclude()
{
include 'not_existing_file.php';
}
Which, I suppose, might also be written as :
public function testLoadFile ()
{
$this->setExpectedException('PHPUnit_Framework_Error');
$result = load_file('/some/non-existent/file');
// code after this point never gets executed
$this->assertFalse($result);
}
For more informations, see Testing PHP Errors
Especially, it says (quoting) :
PHPUnit_Framework_Error_Notice and
PHPUnit_Framework_Error_Warning represent
PHP notices and warning, respectively.
Looking at the /usr/share/php/PHPUnit/TextUI/TestRunner.php file I have on my system, I see this (line 198 and following) :
if (!$arguments['convertNoticesToExceptions']) {
PHPUnit_Framework_Error_Notice::$enabled = FALSE;
}
if (!$arguments['convertWarningsToExceptions']) {
PHPUnit_Framework_Error_Warning::$enabled = FALSE;
}
So maybe you'll have to pass some kind of parameter to activate that behaviour ? But it seems to be enabled by default...
Actually there is a way to test both the return value and the exception thrown (in this case an error converted by PHPUnit).
You just have to do the following:
public function testLoadFileTriggersErrorWhenFileNotFound()
{
$this->assertFalse(#load_file('/some/non-existent/file'));
$this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
load_file('/some/non-existent/file');
}
Notice that to test for the return value you have to use the error suppression operator on the function call (the # before the function name). This way no exception will be thrown and the execution will continue. You then have to set the expected exception as usual to test the error.
What you cannot do is test multiple exceptions within a unit test.
This answer is a bit late to the party, but anyhow:
You can use Netsilik/BaseTestCase (MIT License) to test directly for triggered Notices/Warnings, without ignoring them or converting them to Exceptions. Because the notices/warnings they are not converted to an Exception, the execution is not halted.
composer require netsilik/base-test-case
Testing for an E_USER_NOTICE:
<?php
namespace Tests;
class MyTestCase extends \Netsilik\Testing\BaseTestCase
{
public function test_whenNoticeTriggered_weCanTestForIt()
{
$foo = new Foo();
$foo->bar();
self::assertErrorTriggered(E_USER_NOTICE, 'The notice message');
}
}
Hope this helps someone in the future.

Categories