Using PHPUnit to Test Helper Functions

Let's say I want to test a simple helper that takes a class name as an argument and does a redirect.

How can I check this if a function is called in many places from within multiple controllers? Should I test every class name that was passed as a parameter in all the code (write it myself in the provider function)? Or is there a magic function that does this for me?

+4
source share
2 answers

Your question is the exact reason why dependency injection - when everything is done correctly (not in the way the most popular frameworks are used) - is considered a preface to code testing.

To understand why, let's see how "helper functions" and class-oriented programming make testing your controllers difficult.

class Helpers { public static function myHelper() { return 42; } } class MyController { public function doSomething() { return Helpers::myHelper() + 100; } } 

The whole unit of unit testing is to verify that the "units" of code work in isolation. If you cannot isolate functionality, your tests are pointless because their results may be corrupted by the behavior of other involved code. This can lead to the fact that statisticians call errors of type I and type II: basically this means that you can get test results that can harm you.

In the above code, the helper cannot easily make fun of it to determine that MyController::doSomething works in complete isolation from external influences. Why not? Since we cannot β€œmake fun of” the behavior of the helper method, to ensure that our doSomething method actually adds 100 to the helper result. We adhere to the exact behavior of the helper (return 42). This is a problem that completely excludes the correct orientation of the object and inversion of control. Consider an example of how:

If MyController requests these dependencies instead of using a static helper function, it becomes trivial to mock external influences. Consider:

 interface AnswerMachine { public function getAnswer(); } class UltimateAnswerer implements AnswerMachine { public function getAnswer() { return 42; } } class MyController { private $answerer; public function __construct(AnswerMachine $answerer) { $this->answerer = $answerer; } public function doSomething() { return $this->answerer->getAnswer() + 100; } } 

Now it’s trivial to simply verify that MyController::doSomething really adds 100 to what is returned from the answering machine:

 // test file class StubAnswerer implements AnswerMachine { public function getAnswer() { return 50; } } $stubAnswer = new StubAnswerer(); $testController = new MyController($stubAnswerer); assert($testController->doSomething() === 150); 

This example also shows how the proper use of interfaces in your code can greatly simplify the testing process. Test frameworks such as PHPUnit mock interface definitions very easily in order to accomplish exactly what you want to test the isolated functionality of code blocks.

So, I hope these very simple examples demonstrate how powerful dependency injection is when it comes to testing your code. But more importantly, I hope they demonstrate why you should be wary if your selection frames use static (just another name for global ones), one-stop and helper functions.

+12
source

You cannot check every possible combination of parameters for all the functions necessary for testing; it will take you more time than the life of the universe. So you are using Human Intelligence (some may call this a hoax ;-). Test it only once, in this case with the breadboard controller as a parameter.

Then look at your code and ask yourself if any other object will be transferred, whether it will behave differently. For something that you call a β€œsimple helper,” maybe the answer is no. But if so, how? Create another controller class that mimics this behavior. For instance. this second controller may not have the function that your helper class expects to call. You expect an exception to be thrown. Create a unit test for this.

Repeat until satisfied.

0
source

All Articles