phpphpunitteardown

PHPUnit I need to tear down the 'require_once' call as it is overriding a helper function only for the test


I created a wrapper function in a helper file to wrap a globally used method, like getTimestamp(). The helper file is put in the same namespace as the file I am testing ('The model file'), a namespace like 'Project\Models\TeamName'. The hypothetical model file uses getTimestamp() function and does calculations to check from birth year. I want to test edge cases in the calculations so I overrode the 'getTimestamp()' function to always return 125 in the helper file.

However, this is causing other phpunit tests to fail that use getTimpestamp(). How can I tear it down so the 'require_once' with my helper file is undone, so the rest of the phpunit tests pass? The phpunit test class and SUT are in far away namespaces.

Right now I have a PHPUnit class (located in Project\Testing\PHPUnit\Models\TeamName)

namespace Project\Testing\PHPUnit\Models\TeamName;
require_once '/testing/phpunit/models/teamname/testHelper.php';

use Project\Models\TeamName\MyModel

class MyModelTest {
    const correctAge = 75; 

    public function testAge(){
        $model = new MyModel(); 
        $result = $model -> calculateAgeFromBirthYear(50);
        assertEquals(self::correctAge, $result); 
    }
}

And the helper file (located in Project\Testing\PHPUnit\Models\TeamName)

namespace Project\Models\TeamName; 
function getTimestamp(){
    //today is year 125
    return 125; 
}

And the SUT/model (located Project\Models\TeamName)

namespace Project\Models\TeamName; 
class MyModel {
    function calculateAgeFromBirthYear($birthYear){
        $date = new DateTime();
        $today = $date->getTimestamp(); 
        return $today - $birthYear;
    }
}

I don't want other phpunit classes to inherit a getTimestamp() that always returns 125, I want to undo the requires_once


Solution

  • So this is what worked in my case, not necessarily every case.

    In the MyModel class, I put a function called "getTimestampWrapper", which then called "getTimestamp" and does nothing else. I have my calculateAgeFromBirthYear function look like this now:

    namespace Project\Models\TeamName; 
    class MyModel {
        function calculateAgeFromBirthYear($birthYear){
            $today = getTimestampWrapper(); 
            return $today - $birthYear;
        }
        function getTimestampWrapper(){
            $date = new DateTime();
            $todayWrapper = $date->getTimestamp(); 
            return $todayWrapper;
        }
    }
    

    In MyModelTest, I mocked the MyModel object, then used onConsecutiveCalls with to expect the results properly.

      //make sure a function called 'getTimestampWrapper' is in your model
      $model = $this->getMockBuilder(MyModel::class)
          ->setMethods('getTimestampWrapper')
          ->getMock();
    
      //my onConsecutiveCalls will get me the fake timestamps I want
      $model  ->method('getTimestampWrapper')
          ->will(
              $this->onConsecutiveCalls(...[125, 125, 100])
          );
      //run your assertEquals now
    

    So now when I call $model->calculateAgeFromBirthYear(50) in my unit tests, it will call use 125, 125, 100 for the timestamps