I think you answered your question. The same things that you use to test any web structure apply to Django, such as inversion of control and dependency injection. You can keep it pretty simple in Python, so don't be alarmed and disable it, like Spring.
Why don't you move the code from the class? Your code will still not be dry if for some reason you need the same logic elsewhere. Just because this Django does not mean that good programming principles do not apply.
I would suggest simply abstracting some things in new python classes / modules, such as services (as a concept, not a definition of Django services) and other logical abstractions for accessing data. Then you are completely independent of the request / response life cycle in the Django view. The trend for Django and Rails developers is that every bit of the logic is directly in the model or view. It just leads to divine classes and things that are hard to verify.
You can also facilitate this by thinking of your presentation as a light abstraction that handles everything related to sorting parameters (GET / POST), etc. with the rest of your code and invoking the necessary logic encapsulated elsewhere. IMO, if you want a testable code, 99% of the logic should be out of the network context, unless that is critical to the process. It also makes it easier to work in the background and in parallel.
As a result, you should use regular python modules and classes that are easy to test, since they do not have direct dependencies on HTTP. If you need to mock HTTP, you can simply make fun of the request object. You are fortunate that the python / django combination makes it easy to dig out and mock these things as simple dicts / kwargs.
One thing that I understood with the help of class-based views is that they are good for using with mixins and enforcing some conventions (returning json, opening graph properties, etc.), but using more "advanced" classes view-based ones that directly require such models since DetailView simply complicates things unnecessarily. These views are good for admin screens, but for real applications, help is more than painful. They do their best to test and kill performance if you don't find a nice, seamless way to integrate caching layers, etc. At the moment, it usually just inherits View or TemplateView and must be executed with it.
When it comes to DB, mocking something, create your own layouts and view your business logic. Then it doesnβt matter what you input / output if it matches a specific set of rules and interfaces. For example, see Mixer . You can also just create / destroy temporary databases during testing. One way is to create separate settings modules for dev / staging / production / testing, etc. And dynamically load them depending on the environment. This way you can avoid damaging your working developers database when doing unit tests. Of course, this is more suitable for the form of integration testing, but you probably should do it too. The above solutions are common in other ORMs such as Hibernate.
According to the previous, you can do something like the code below in your settings to use the in-memory database for unit testing. In the end, however, you still need to consider integration testing against your actual type of data store, e.g. MySQL
if 'test' in sys.argv: DATABASES['default']['ENGINE'] = 'sqlite3'
; TL; DR
Put your logic outside the class representations in the appropriate objects and modules.
Do not block yourself while trying to make various class-related views for working on real applications and in each use case; collapse your own.
Use generally good TDD principles, such as IOC, pass the necessary parameters to designers, freely move things, avoid excessive requirements for state requirements (in particular, HTTP).
- Avoid database dependencies by creating standard mock-up objects (see No. 3) and passing through service interfaces (see No. 1).