php - unit testing and Static methods -


reading , picking on unit testing, trying make sense of the following post on explains hardships of static function calls.

i don't understand issue. have assumed static functions nice way of rounding utility functions in class. example, use static functions calls initialise, ie:

init::loadconfig('settings.php'); init::seterrorhandler(app_mode);  init::loggingmode(app_mode);  // start loading app related objects .. $app = new app(); 

// after reading post, aim instead ...

$init = new init(); $init->loadconfig('settings.php'); $init->loggingmode(app_mode);  // etc ... 

but, few dozen tests had written class same. changed nothing , still pass. doing wrong?

the author of post states following:

the basic issue static methods procedural code. have no idea how unit-test procedural code. unit-testing assumes can instantiate piece of application in isolation. during instantiation wire dependencies mocks/friendlies replace real dependencies. procedural programing there nothing “wire” since there no objects, code , data separate.

now, understand post static methods create dependencies, don't grasp intuitively why 1 cannot test return value of static method regular method?

i avoiding static methods, of liked having idea of when static methods useful, if @ all. seems post static methods evil global variables , should avoided as possible.

any additional information or links on subject appreciated.

static methods aren't harder test instance methods. trouble arises when method--static or otherwise--calls other static methods because cannot isolate method being tested. here typical example method can difficult test:

public function finduser($id) {     assert::valididentifier($id);     log::debug("looking user $id");  // writes file     database::connect();                 // needs user, password, database info , database     return database::query(...);         // needs user table data } 

what might want test method?

  • passing other positive integer throws invalididentifierexception.
  • database::query() receives correct identifier.
  • a matching user returned when found, null when not.

these requirements simple, must setup logging, connect database, load data, etc. database class should solely responsible testing can connect , query. log class should same logging. finduser() should not have deal of this, must because depends on them.

if instead method above made calls instance methods on database , log instances, test pass in mock objects scripted return values specific test @ hand.

function testfinduserreturnsnullwhennotfound() {     $log = $this->getmock('log');  // ignore logging calls     $database = $this->getmock('database', array('connect', 'query');     $database->expects($this->once())->method('connect');     $database->expects($this->once())->method('query')              ->with('<query string>', 5)              ->will($this->returnvalue(null));     $dao = new userdao($log, $database);     self::assertnull($dao->finduser(5)); } 

the above test fail if finduser() neglects call connect(), passes wrong value $id (5 above), or returns other null. beauty no database involved, making test quick , robust, meaning won't fail reasons unrelated test network failure or bad sample data. allows focus on matters: functionality contained within finduser().


Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -