Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change a method on a PHPUnit Mock after I've set it?

I'm trying to create a mock instance in setUp with default values for all of the overridden methods and then in several different tests change the return value for some of the methods depending on what I'm testing without having to set up the entire Mock. Is there a way to do this?

This is what I tried, but the naive approach doesn't work. The method still returns the value from the original expectation setup.

First setup:

$my_mock->expects($this->any())         ->method('one_of_many_methods')         ->will($this->returnValue(true)); 

In another test before a different assert:

$my_mock->expects($this->any())         ->method('one_of_many_methods')         ->will($this->returnValue(false)); 

Duplicate to this question: PHPUnit Mock Change the expectations later, but that one got no responses and I thought a new question might bring the issue to the fore.

like image 470
Brian Ramsay Avatar asked Nov 29 '12 18:11

Brian Ramsay


People also ask

Which method is used to create a mock with PHPUnit?

PHPUnit provides methods that are used to automatically create objects that will replace the original object in our test. createMock($type) and getMockBuilder($type) methods are used to create mock object. The createMock method immediately returns a mock object of the specified type.

What is mock method?

Mocking means creating a fake version of an external or internal service that can stand in for the real one, helping your tests run more quickly and more reliably. When your implementation interacts with an object's properties, rather than its function or behavior, a mock can be used.

What is laravel mocking?

When testing Laravel applications, you may wish to "mock" certain aspects of your application so they are not actually executed during a given test. For example, when testing a controller that dispatches an event, you may wish to mock the event listeners so they are not actually executed during the test.


1 Answers

In cases where you use the same method more than once, you should use the "at" declaration with the proper count where executed in the code. This way PHPUnit knows which one you mean, and can fulfill the expectation/assertion properly.

The following is a generic example where method 'run' is used several times:

public function testRunUsingAt()     {         $test = $this->getMock('Dummy');          $test->expects($this->at(0))             ->method('run')             ->with('f', 'o', 'o')             ->will($this->returnValue('first'));          $test->expects($this->at(1))             ->method('run')             ->with('b', 'a', 'r')             ->will($this->returnValue('second'));          $test->expects($this->at(2))             ->method('run')             ->with('l', 'o', 'l')             ->will($this->returnValue('third'));          $this->assertEquals($test->run('f', 'o', 'o'), 'first');         $this->assertEquals($test->run('b', 'a', 'r'), 'second');         $this->assertEquals($test->run('l', 'o', 'l'), 'third');     } 

I think this is what you're looking for, but if I'm misunderstanding please let me know.

Now in terms of mocking anything, you can mock it as many times as you want, but you are not going to want to mock it with the same name as in the setup, else every time you use it you are referring to the setup. If you need to test similar methods in different scenarios, then mock it for each test. You could create one mock in the setup, yet for one test use a different mock of a similar item within an individual test, but not of the global name.

like image 88
jsteinmann Avatar answered Sep 27 '22 18:09

jsteinmann