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?
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.
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.
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.
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
Related
In Ember.js, I currently want to test a UI feature present. Essentially, once a model variable changes, I expect to see a UI element appear (a checkmark). I have tried creating a model within the acceptance test but this unfortunately did not work as I did.
I just wanted to know which function to use to set model variables.
A model typically would involve unit tests, but like you've said you're testing the visual result of something being set on a model. I would recommend an integration test. If you are able to refactor (or maybe this is the case already), the part of the template into a component then you can create an ember test for the component and pass in the model set up perfectly how you would like.
If this test really does depend on the model being setup a specific way I would look at how your application sets up that model to begin with and try to replicate those actions with click and fillIn helpers. Another way is say, your application wants to setup a user but relies on a network request to do this, then you could use pretender.js and fake the response to that request so that the application's inputs are setup from the network in the way you're after.
I would really try to do this an acceptance test though, the composable nature of components allows them to be tested in stricter isolation, these tests will run faster, and you're worrying less about side effects.
In my Django site I use Django REST framework. To not repeat myself, I created a couple mixins to simplify writing my view sets (here is an example of a similar style of mixin).
My question is how do I go about testing such a mixin? If it was a regular view exposed on some URL, I would use APITestCase provided by the framework, but since my mixin is not a standalone object and needs to be inherited from to be actually useful, this way of testing is not applicable.
Is there some way to mock the rest of the view? Or do I have to create a dummy application using this mixin and do integration tests?
You should test Django REST Framework view mixins the same way that you should test standard Django view mixins. You test it when attached to a view or you mock up all of the parts of a standard view that it would rely on.
You should be able to test mixins when attached to views in the same way that you would test standard views, because mixins should behave consistently in ways that are testable. You may need to create test views for each case that the mixin works with, which is what we had to do with DRF JSON API when creating the tests.
In the case of Django REST Framework Bulk, the best way would probably be to create a view that has the mixins attached to it, and test that it responds as expected. For the bulk mixins, lets assume that the following needs to be tested:
Single object POST still works
Multiple object POST on the list
Multiple object PUT on the list
Multiple object PATCH on the list
Multiple object DELETE on the list
This would require at least five tests, most likely split up for what they are testing. You would also need to make sure that the tests cover the hooks that are also being called, as well as any side effects that are expected.
The Python unittest.mock module helps a lot with mocking views (if you want to do that) and allows you to determine if methods (such as the hooks) are called.
Hi I'm developing a Play 2 app.
By convention there are views, models and controllers. Views call controllers (by routes) and controllers call models. Models are filled with data by database calls initiated by the given finder.
Well, now I created my first controller test. The controller method I want to test is a method that calls a user model itself (User user = User.findByName("someName");). So this means this method is coupled to this model class. To test this method I have to set up an in-memory database with testdata which is called by the finder of the user model during the test. But this makes my unit test to an integration test. Because every controller method is static I can't inject a mock of the model. Is this the right way Play recommends? Or is there a way to substitute models by mocks during testing.
I thought about accessing models by a ModelProvider or so that is able to substitute models by mocks in the Tests.
What do you think? Or is this overkill?
Thanx
Nick
I also found this difficult. What I did eventually is to use a factory to get the model class, and injected a mock class instead of the original one.
If you replace the model with a simple in memory database, it is still considered a unit test. This could also do the trick for you and shouldn't be very difficult to set up.
One thing that was difficult for me to find, is how to set up a different conf file for testing. This code snippet does the trick. make sure you have a test.conf file with the mock in memory database configured there.
protected Configuration additionalConfigurations;
protected AbstractTest()
{
Config additionalConfig = ConfigFactory.parseFile(new File("conf/test.conf"));
additionalConfigurations = new Configuration(additionalConfig);
start(fakeApplication(additionalConfigurations.asMap(),fakeGlobal()));
}
just a Provocative Question
why do you thing we should unit test controllers in MVC why not just write test against models or service layer.
A good example should be this one (in BDD-style):
Given the user 'snehal' does not exists
When I create a new user with credentials 'snehal' and 'so#123'
And I log in with this user
Then I should see a welcome page
This scenario is expecting that new user should see a welcome page when they log in for the first time. At least for me, this is the Controller's job and is a nice feature that I would like to make sure it is works.
One point is testing your routes.
The controllers can contain quite a bit of critical functionality. If your app doesn't have critical logic here, it may not be necessary to unit test quite so heavily. But I'd at least write a few tests to make sure your routes are set up correctly.
How do I unit-test a Zend_Form form class I wrote for my application?
I aspire to have a 100% code coverage, so just testing each controller that uses it, doesn't seem enough, but I could be missing something in the UnitTest approach..
Unit testing stands for testing of units, so you should
test your Zend_Form based class - you can pass any test data to populate method
than test your controller separately - create mock for your Zend_Form based class, because you are going to test it again, this requires some sort of factory or dependency injection in controller.
The LoginForm class in the example from comment doesn't provide more functionality than setting elements, validators, decorators etc., so this may be tested easily. If you want to test the controller, you should pass it (e.g. as constructor parameter, see Dependency injection) some mock of LoginForm. If you want to test controller and form intergration (which is not unit test, but one can do it also with PhpUnit), you can use controller's method setRequest to set fake request data.
You can try it with Selenium. This way you can prepare inputs and expected outputs. However, it requires that you actually display the form in a browser, so your controller has to work as well.
What about writing test cases that POST form data to your action controller? This way you can generate as many different user inputs as you want and you can check whether your form validation works or whether you get correct error messages.