8

It may seem silly, hope not, but I want to create a service that will return mock objects for people that uses my project so they can mock all the classes from my project and test their code.

My idea was to offer this kind of service so it can be called inside other project's test cases and obtain the appropriate mock for each test.

Is that possible? Or there are other ways to do that. Btw, I can't use any mocking library because of project's limitations.

6
  • If the mocks are to be used in tests then why do you need mocks outside of test cases? If you don't want to include your full project code you can always just include the interfaces. Commented Feb 17, 2015 at 17:01
  • There will be tests in several projects and all of them need mocks so I wanted to have like a repository of mocks so every project can access it and doesn't need to create their own mocks Commented Feb 17, 2015 at 17:06
  • Why not have a repository of your actual code? Then everyone can mock against the real thing. Commented Feb 17, 2015 at 17:07
  • Because create a mock for one of these classes will require a lot of code lines so I wanted to save them the work, also that way I can maintain the mocks myself so if I add a new method I can change the mock on my own code. Commented Feb 17, 2015 at 17:11
  • What exactly do you mean by mock? I have a feeling you don't mean $unit->getMock("MyClass");? Commented Feb 17, 2015 at 17:15

2 Answers 2

11

Yes, it is possible. Under the hood the getMock method uses the PHPUnit_Framework_MockObject_Generator class. So you can use it directly:

PHPUnit_Framework_MockObject_Generator::getMock($originalClassName, $methods)

But you will lose all the expectation shortcuts like $this->once(). You will have to instantiate the expectations on your own:

$mock->expects(\PHPUnit_Framework_TestCase::once())

Look at the PHPUnit source code to see how the mocks are build

3
  • Thanks, that's what I did (I was preparing the answer today :) ) but instead of using the PHPUnit_Framework_TestCase static methods I use the matchers directly, for example: \PHPUnit_Framework_MockObject_Matcher_InvokedCount($numTimes) or \PHPUnit_Framework_MockObject_Stub_ReturnSelf() But in the end it's just the same. Thanks a lot Commented Feb 19, 2015 at 8:42
  • 2
    The getMock() method is not static (PHPUnit 3.7.28), so you should call it from an instance: $mockGen = new \PHPUnit_Framework_MockObject_Generator(); $mock = $mockGen->getMock($originalClassName, $methods); Commented Dec 23, 2015 at 9:46
  • 3
    In the more recent versions of PHPUnit, you need to use (new PHPUnit\Framework\MockObject\Generator())->getMock(...) Commented Dec 28, 2017 at 14:11
2

If you build the mock outside the TestCase, it will not be accounted as a mock and it's expectations won't be checked automatically.

If your mock builder service is supposed to be used exclusively from PHPUnit tests (even if those tests are not related) you can have the testcase instance passed to the mock builder, so you can build the mock the usual way:

class MockBuilderService
{
    private $test;

    public function __construct(PHPUnit_Framework_TestCase $test)
    {
        $this->test = $test;
    }

    public function buildVeryComplexMock()
    {
        $mock = $this->test->getMock('MyClass');
        $mock->expects($this->test->once())
             ->method('foo')
             ->willReturn(1);      
        return $mock;      
    }
}

So you can use it from your test:

class ATest extends PHPUnit_Framework_TestCase
{
    public function testFoo()
    {
        $mock_builder = new MockBuilderService($this);
        $complex_mock = $mock_builder->buildVeryComplexMock($mock_configuration);

       // the mock expectations will be checked as usual
    }

}
1
  • Thanks for the answer but I didn't want to make the other projects pass the tests cases through the arguments so I went with a solution similar to the one proposed by @Darhazer. Commented Feb 19, 2015 at 8:46

Your Answer

By clicking β€œPost Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.