james
james

Reputation: 3583

Mock a method in the same class being tested

I want to mock a method in the same class that I am testing.

ClassA {
   function hardToTest($arg) {
      // difficult to test code
   }

   function underTest() {
      return $this->hardToTest('foo');
   }
}

I was thinking that I could use reflection to do this, but maybe it is just a sign that I should move hardToTest into another object.

Upvotes: 26

Views: 20510

Answers (3)

tereško
tereško

Reputation: 58454

What exactly is the reason what method is hard to test ?

If the method is protected, and you really really want to test it, then you can just extend your ClassA and make the hardToTest($arg) public.

The bottom line is that you shouldn't modify the class only because you need to write unittest for it. And in general, the private and protected methods should not be tested - you should test only the public interface.

Upvotes: -1

David Harkness
David Harkness

Reputation: 36562

This test will succeed if underTest() passes 'foo' to hardToTest(). This is known as a partial mock in PHPUnit's documentation because you are mocking only some of the methods.

ClassATest {
    function testUnderTest() {
        $mock = $this->getMock('ClassA', ['hardToTest']);
        $mock->expects($this->once())
             ->method('hardToTest')
             ->with('foo');
        $mock->underTest();
    }
}

I agree with your instincts that this need may be a code smell telling you that this class is doing too much.

PHPUnit 5.4+

Since getMock() was deprecated in 5.4, use getMockBuilder() instead:.

$mock = $this->getMockBuilder('ClassA')
             ->setMethods(['hardToTest'])    // onlyMethods in 8.4+
             ->ge‌​tMock();

Upvotes: 25

james
james

Reputation: 3583

What I resorted was creating a sub class of my system under test with the relevant method stubbed out.

Upvotes: 0

Related Questions