PHPUnit testing with closures

Tram Ho

4 months ago, I was assigned a task to write Unit tests for the project, this is also the first time I was exposed to PHPUnit. While writing tests encountered many problems that make it difficult to write tests, this article I would like to share one of the problems I encountered offline.

My project is Digmee project, because I cannot share the code out, I will use the most basic examples to describe.

One of the problems I encountered and took a lot of time for it is: How to test one function is the parameter of another function?

I have found out and these are called Anonymous functions, so …

What are anonymous functions?

In PHP, there is a concept that is used quite a lot, especially with modern frameworks like Laravel, which is a function parameter of another function, also known as Anonymous functions, also commonly known as Closure.

For example:

The get function above has 2 parameters, the first parameter is 1 string and the second parameter is an anonymous functions. The problem is how to test those anonymous functions?

To be able to test, we will use: …


We will use this example:

Now we will test PostService in Unit test , unlike Integration test must actually call the dependency method (PostRepository), must connect different types of database or must run through many functions of many classes. Unit tests simply make sure the method of the dependency is called and must be called correctly.

The test code will look like this:

Here we use Mockery to simulate a mocked object. In the above example that we wish mockery by the method testGetPostsByUser of class PostService ensure the following:

  • Must call the getPostsByUser method of PostRepository
  • Must call exactly 1 time
  • Must call with exactly one parameter of $userId
  • Assuming the function of PostRepository returns any abcxyz, then the function of PostService must return exactly that.

Later, if someone in the team changes the function code in PostService , wants to pass another parameter, or wants to call the function 69 times instead of just calling once … then I expect that test must be failed to also know the way that counts. Either go (tat) for a play because you dare change the behavior of the function or begged people to accidentally make people become pregnant, you have to go and be responsible.

So … What would Mockery associate with Anonymous functions?

Mock anonymos function

Modifying the code a bit, PostService will use the whole CacheService to retrieve post data from the cache. The getFromCache function will have 2 parameters, the first parameter is cacheKey , the second parameter is an Anonymous functions to retrieve data, if cacheService not find data by cacheKey , it will call this function to retrieve data to save to the cache then return it.

The new code will be:

My problem in Digmee project is this, I don’t know how to test this so-called Anonymous functions …

And I found Mockery that supports how to validate paramater with Mockery :: on and the parameter is also an anonymous functions.

The test code will look like this:

Here we have mocked [email protected] to return a sample data of posts, and this function is called again in the Anonymous functions of CacheService , so we will verify by calling this Anonymous functions, the result will be equal to the data. Whether the post has mocked above.

I refer to this link .

And finally, the assert data returned by [email protected] also returned the exact results as we wanted.


Above is my practical experience encountered when writing tests, and I have found a lot to be able to solve it ( for example ).

There are many other issues but I’m a bit lazy to share ? I hope you raise your bow (bow).

Thank you for reading!

Share the news now

Source : Viblo