Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

testing error_log with PHPUnit

Tags:

php

phpunit

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.

like image 637
Donoven Rally Avatar asked Jul 26 '15 12:07

Donoven Rally


People also ask

What is PHPUnit testing?

PHPUnit is a unit testing framework for the PHP programming language. It is an instance of the xUnit design for unit testing systems that began with SUnit and became popular with JUnit. Even a small software development project usually takes hours of hard work.

How do I log into PHPUnit test?

If it's not an option for You and You still want to log from the PHPUnit test cases, You have 3 options: Use the built-in logging functionality (documentation), which can be configured through either phpunit. xml file or the command line arguments (documentation);

Which method is used to create a mock with PHPUnit?

PHPUnit provides methods that are used to automatically create objects that will replace the original object in our test. createMock($type) and getMockBuilder($type) methods are used to create mock object. The createMock method immediately returns a mock object of the specified type.

Why do we use PHPUnit?

PHPunit is mainly used for unit testing. When developer develops any web application, there might be chances of bugs coming into picture during the course of development. It is really hard to resolve one bug after another. PHPunit helps to reduce such types of bugs.


2 Answers

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, ";
}
like image 140
Alister Bulman Avatar answered Nov 06 '22 16:11

Alister Bulman


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

like image 28
heiglandreas Avatar answered Nov 06 '22 15:11

heiglandreas