Group testing with mocks (PHP)

I have a class like:

class Foo { function getCurrentBar() { $model = Query::findByPk($this->getSession()->get('current_bar')); // Pseudocode... return $model; } } 

So basically, in my application there is one point at a time, and it is stored in the session as a whole. I often call a helper function that will find an instance of the model and make a db request. There is also caching, but now it does not matter.

My question is: how do I unit test with this? There are classes that I'm testing that need this. I think I could change the session to contain an identifier, but then that means I need to have the appropriate model in the database.

Would there be a better way to add the setCurrentBar() method for unit testing purposes only? Then I could mock the bar and install it, and it will be used for all unit tests. It makes sense?

+4
source share
3 answers

The answer is really an injection of dependencies, but the dependency you want to control is the source of the bars, not the panel itself.

 class Foo { private $query; function __construct($query) { $this->query = $query; } function getCurrentBar() { $model = $this->query->findByPk($this->getSession()->get('current_bar')); // Pseudocode... return $model; } } 

So, in your production code there is

 $query = new Query() // assuming findByPk() is made a normal non-static method $realFoo = new Foo($query); 

but for unit testing ...

 $testFoo = new Foo(new MockQuery()); 

where MockQuery is a mock version of your Query class that returns mock bars.

+6
source

You can try dependency injection .

Pass Bar instance to Foo constructor

 class Foo { private _bar; function __construct (Bar $bar) { $this->_bar = $bar; } public function getCurrentBar() { return $this->_bar; } } 

You can then enter your Bar Object layout when you run the test.

0
source

You can also test a partial layout of an object over a period of time until the DI system is installed.

 class Foo { function getCurrentBar() { $model = $this->getQueryResult($this->getSession()->get('current_bar')); // Pseudocode... return $model; } function getQueryResult($queryParams) { return Query::findByPk($queryParams); } } 

Then run a test that is a bit like this ...

 $myObjectToTest = $this->getMock('Foo', array('getQueryResult'), array(), '', true, true, true); $myObjectToTest->expects($this->once()) ->method('getQueryResult') ->with($whateverTheQueryParametersAre) ->will($this->returnValue($someResult)); $myObjectToTest->getCurrentBar(); 
0
source

Source: https://habr.com/ru/post/1392475/


All Articles