0
votes

I'm trying to test a static method on a class, but it relies on a static array property that doesn't get reset between tests, so I though I could create a mock class & test against that.

The only problem is that the mock class static method is not returning the value as the original static method does.

Here's my class...

class Thing {
    static public function doThing() {
        return 'yeah!';
    }
}

... and here's be test class...

class ThingTest {
    public function testDoSomething() {
        $mock_class = $this->getMockClass('Thing');
        $this->assertEqual('yeah!', $mock_class::doThing())
    }
}

This test fails with the message "Failed asserting that null matches expected 'yeah!'."

What am I missing here? I thought not specifying the methods on the getMock() call meant that the original methods carried over, but clearly not. :o(

Any pointers would be great. Thanks.

Edit

I typed this up from memory, rather than from copying code, as I'd made further change to try to resolve this. After writing more tests for mock objects I realised that if you pass array() as the second parameter ($methods) to getMock[Class] then it stubbed out all the methods, & I believe this is what I had actually done. I was doing this, as I also wanted to pass the constructor parameter in the 3rd argument. The code probably looked more like this...

class ThingTest {
    public function testDoSomething() {
        $mock_class = $this->getMockClass(
            'Thing',
            array(),
            array( 'something' )
        );
        $this->assertEqual('yeah!', $mock_class::doThing())
    }
}
3
When working with Statics, PHPUnit has limitations phpunit.de/manual/3.7/en/test-doubles.html. You might need to use Mockery instead.Steven Scott
Thanks for that, Steven. Not come across that before.TobyG

3 Answers

0
votes

Maybe $mock_class is an object, not a string class name? Try to use next:

class ThingTest {
    public function testDoSomething() {
        $mock_class = $this->getMockClass('Thing');
        $this->assertEqual('yeah!', Thing::doThing())
    }
}

Is this work?

0
votes

You forgot extending by PHPUnit_Framework_TestCase.

class ThingTest extends PHPUnit_Framework_TestCase {
  public function testDoSomething() {
     $mock_class = $this->getMockClass('Thing');
     $this->assertEqual('yeah!', $mock_class::doThing())
  }
}
0
votes

You shouldn't mock the class containing the method you want to test. If you mock the class, you can't call any method either before you haven't defined it via

-> expects('methodName') 
-> with($this->equalTo($parameter),[$this->equalTo($parameter2),...]) 
-> will($this->returnValue($value))

. Mocking is used to reduce complexity of a test. Let's say you want to test a function that looks like this:

class test{
    private $someClass;

    public function __construct(SomeInterface $someClass){
        $this -> someClass = $someClass;
    }
    public function test(){
        $someVariable = $this -> someClass -> doSomething();
        changeSomething($someVariable);
        return $someVariable;
    }
}

If you don't mock someClass, you'd have to test the whole code of someClass -> doSomething. But that is not what you want to do. You just want to use the return of the function doSomething. That is the point where you need a mock. It reduces the complexity of your test and offers REAL UNIT tests instead of testing the whole app.

So what you need to do is:

class ThingTest {
    public function testDoSomething() {
        $class = new Thing();
        $this->assertEquals('yeah!', $class::doThing());
    }
}

There is no need for a mock.