1
votes

I'm having difficulties writing tests for my Zend Framework 2 controllers: (although, this could be generalized to other frameworks) I have controllers which process forms that do CRUD operations on doctrine 2 entities (although that again, it can be generalized to other ORMs)

Lets assume I have one "User" controller with an "add" action and corresponding "User" form and "User" Entity. And lets say the user entity is linked in a "Many-to-One" relation to a "Company" entity, and in a "Many-to-many" relation to a "Group" entity (using a Collection "groups" field).

Now lets say I have a form to add new users, where you select the user's name, company, and groups.

Now, in my "add" action I process the POST'd User form and (if it validates), hydrate the User entity, its related entities, and persists it. My question is: how, and what exactly should I test, when testing the "add" action of the form?

  1. I assume that since I'm testing the controller and not the entities, I should not be using a real database, and therefore mock the entity. But I don't see how this could be (easily) done; this entity rather complicated and has other entities and collections in that are related to them. if I try to mock it, I assume that since the entity gets hydrated I will have to mock each of its setter and getter methods. But If I try to mock the "getGroups()" method for example, what should I make it return? a real Collection of real Group entities? or another mock? same goes for the "company" property. Seems like it doesn't make sent to mock this complicated graph, which will definitely repeat itself in other controllers' tests and also irrelevant to a "User" test.

  2. There is also the form issue: in the controller, I am using a "user" form. so unless I mock it, it will actually be tested too - is that ok? on one side, a unit test should only test the relevant part of the code and nothing else, but on the other hand - there are so many things that gets "tested" along the way, so its impossible to mock every single thing.

Since this seems to me like there is no good solution, I an now leaning towards functional testing with a test datbase, but I would love it if I could understand the proper way to unit test.

2

2 Answers

0
votes

I have found that with ZF2, the controller tests end up being more of what is considered an "integration" test. Actually testing most of the logic in the models rather than only the code in the controller itself. In that regard, mock out what you need to so that your code doesn't actually hit the database and post data to the action using most of your actual objects.

This helps in that you get make sure that all the connections between your models work. Don't get too caught up in what is or isn't a "unit" test. Make a test that is useful for you and gives you confidence that your code works correctly.

0
votes

This is what you should test for Add Method.

If can access add method by route.
If is redirected to a '404 warning page' when access with a irregular character.
If shows validation message if a post was empty.
If shows validation message for duplicate entries.
By checking validations messages by CSS/XPATH

If inserts successful by using the right values on POST.
By Checking Values Entities Assertion from Post.

All the same you can do for edit method.

It's a simplest way possible to secure your controllers. Remember that phpunit is for testing unit of software, and controller is a unit connected to a Model or a API. For "Controllers" Action I do the test I described above also a "Acceptante test" by codeception Acceptance Testing