Play Framework testing and loose coupling - unit-testing

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()));
}

Related

How do I set model variables within an acceptance test?

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.

How to test view mixins in Django REST Framework?

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.

Unit testing (ZF2) controllers which process forms and (doctrine 2) entities

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

Where to put business logic in django

For example, Account 1--> *User --> 1 Authentication
1 account has multiple users and each user will have 1 authentication
I come from java background so what I usually do is
define these classes as java beans (ie, just getter and setter, no logic attached)
create AccountManager ejb class, define create_account method (with takes 1 account, list of users)
preparing data in the web layer, then pass data into AccountManager ejb, for instance:
accountManager.createAccount(account, userList)
But in django, the framework advocates that you put domain logic into model classes (row level) or associated manager classes (table level), which makes things bit awkward. Yes, it is fine that if your logic is only involves one table, but in the real application, usually each step will involve multiple different tables or even databases, so what should I do in this case?
Put the logic into View? I don't think this is good practice at all. or even overwrite the save method in model class, passing in extra data by using **kwargs? then the backend will break.
I hope this illustrates my confusion with where business logic should be placed in a django application.
Not sure if you've read the section on Managers in Django, it seems to solve your current situation. Assuming you have the following Account model defined, User is built-in.
# accounts/models.py
class AccountManager(models.Manager):
def create_account(self, account, user_list):
...
class Account(models.Model):
objects = AccountManager()
Feel free to separate your manager code in a separate file if it gets too big. In your views:
# views.py
from accounts.models import Account
Account.objects.create_account(account, user_list)
The business logic is still in the models.
EDIT
The keyword here is override, not overwrite. If you override the model's save method, you have to keep in mind that any create, update operations from within your web app and admin will use this new functionality. If you only want those business logic to happen once in a specific view, it might be best to keep it out of save.
I guess you can put your business logic in its own regular class. You will have to instantiate that class each time you need to run your business logic. Alternatively, you can put your business logic as a static function in this new class if you want to skip the OOP approach.
What I'm doing is that most of my apps have service.py file with business logic. This is because if I need a function that works with models from multiple apps I simply cannot do this:
# shop/models.py
from auth.models import User, Team
This code will be stuck in circular reference loop.
But I'm gonna move most likely from service.py to app with structure like this:
service/
auth.py
customers.py
another_set_of_functions.py
...
Well the example that you illustrated above with the accountManager.createAccount(account, userList) seems like something that could be easily done my adding a createAccount method to the account model. If you feel the need to take business logic outside of the model though you could always just create a new module that host your business logic, and then import and used in in your views.

How do I test a Zend_Form class?

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.