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.
Related
I am thinking of using dockyard validations in my project
I have options as to how to use the Validations-Mixin from dockyard
Approach 1 to have a BaseController which will mixin this Validations-Mixin and get the functionality in all controllers
Approach 2 use the Mixin directly.
Pros of 1
no need to import ember-validations in every file and mixin manually , and I get the functionality of validations in all the controllers.
Cons of 1
Validations might not be required in all the controllers , may be it's required only in 50% of the cases, also might reorder the way existing controllers add the mixins.
Pros of 2
Simple, only who need the functionality will import and use it.
Cons of 2
importing in each file where required and adding the mixin.
I think you should use that mixin directly. Why?
Because there is no need to extend it in every controller in your app. Extending mixins is a way to obtain shared functionality between controllers that share that functionality. I am pretty sure that not every controller in your app needs validation.
From my experience I can say that only some percent of controllers use validations (it depends on the app, but it's just a rough mean value). Import the mixin where it's needed.
I'm extending Django QuerySet by subclass (say MyQuerySet), and I would like to guarantee that my implementation does not break any existing functionality of QuerySet.
How can I test MyQuerySet against existing Django tests on QuerySet without having to replicate them?
For concreteness, let's consider the example of tests of prefetch_related, found in django/tests/prefetch_related package.
I would like to run all those tests on MyQuerySet. However, those tests are implemented using the default manager of the models in the package. Does anyone have any idea how to e.g. duck type objects to a custom manager that uses MyQuerySet?
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()));
}
I'm working on an e-commerce framework for Django. The chief design goal is to provide the bare minimum functionality in terms of models and view, instead allowing the users of the library to extend or replace the components with their own.
The reasoning for this is that trying to develop a one-size-fits-all solution to e-commerce leads to overcomplicated code which is often far from optimal.
One approach to tackling this seems to be using inversion-of-control, either through Django's settings file or import hacks, but I've come up against a bit of a problem due to how Django registers its models.
The e-commerce framework provides a bunch of abstract models, as well as concrete versions in {app_label}/models.py. Views make use of Django's get_model(app_label,model) function to return the model class without having to hard-code the reference.
This approach has some problems:
Users have to mimic the structure of the framework's apps, ie the app_label and effectively replace our version of the app with their own
Because of the way the admin site works by looking for admin.py in each installed app, they have to mimic or explicitly import the framework's admin classes in order to use them. But by importing them, the register method gets called so they have to be unregistered if a user wants to customise them.
The user has to be extremely careful about how they import concrete models from the core framework. This is because Django's base model metaclass automatically registers a model with the app cache as soon as the class definition is read (ie upon __new__), and the first model registered with a specific label is the one you're stuck with. So you have to define all your override models BEFORE you import any of the core models. This means you end up with messy situations of having a bunch of imports at the bottom of your modules rather than the top.
My thinking is to go further down the inversion-of-control rabbit hole:
All references to core components (models, views, admin, etc) replaced with calls to an IoC container
For all the core (e-commerce framework) models, replace the use of Django's base model metaclass with one that doesn't automatically register the models, then have the container explicitly register them on startup.
My question:
Is there a better way to solve this problem? The goal is to make it easy to customise the framework and override functionality without having to learn lots of annoying tricks. The key seems to be with models and the admin site.
I appreciate that using an IoC container isn't a common pattern in the Django world, so I want to avoid it if possible, but it is seeming like the right solution.
Did you look at the code from other projects with a similar approach?
Not sure if this way covers your needs, but imo the code of django-shop is worth to look at.
This framework provides the basic logic, allowing you to provide custom logic where needed.
customize via models
eg see the productmodel.py
#==============================================================================
# Extensibility
#==============================================================================
PRODUCT_MODEL = getattr(settings, 'SHOP_PRODUCT_MODEL',
'shop.models.defaults.product.Product')
Product = load_class(PRODUCT_MODEL, 'SHOP_PRODUCT_MODEL')
customize via logic/urls
eg see the shop's simplevariation-plugin
It extends the cart-logic, so it hooks in via urlpattern:
(r'^shop/cart/', include(simplevariations_urls)),
(r'^shop/', include(shop_urls)),
and extends the views:
...
from shop.views.cart import CartDetails
class SimplevariationCartDetails(CartDetails):
"""Cart view that answers GET and POSTS request."""
...
The framework provides several points to hook-in, the simplevariation-plugin mentionned above additionally provides a cart-modifier:
SHOP_CART_MODIFIERS = [
...
'shop_simplevariations.cart_modifier.ProductOptionsModifier',
...
]
I worry that this explanation is not very understandable, it is difficult to briefly summarize this concept. But take a look at the django-shop project and some of its extensions: ecosystem
I've begun diving into Django again and I'm having trouble finding the parallel to some common concepts from my life in C#. While using .NET MVC I very often find myself creating a base controller which will provide a base action implementation to take care of the type of stuff I want to do on every request, like retrieving user information, getting localization values.
Where I'm finding myself confused is how to do this in Django. I am getting more familiar with the MVT concept but I can't seem to find how to solve this scenario. I've looked at class based views and the generic views yet they didn't seem to work how I expected. What am I missing? How can i create default logic that each view will be instructed to run but not have to write it in each view method?
If it is truly common for your whole site you use middleware. If it is only common for some views, the way to go in my opinion is to create decorators for those views. I never use class-based views because I tend to keep views simple and put more logic into models, so I have no need for classes there.