3

I am using django 1.9 and one of my models has a many-to-many field. For example:

class PhoneNumber(models.Model):
    number = models.CharField(max_length=255)
    ...

class Person(models.Model):
    name = models.CharField(max_length=255)
    phone_numbers = models.ManyToManyField(PhoneNumber)
    ...

(please ingnore the fact that I am saving the number as a CharField).

I want to write unit test for a serializer that I created with Django Rest Framework. For this purpose, I want to create instances of Person without relying on the database. I tried creating the object by

person = Person(...)

but I get the following error:

object needs to have a value for field “…” before this many-to-many relationship can be used

Is it possible to mock model instances without relying on first writing the instance to the database?

gire
  • 1,105
  • 1
  • 6
  • 16
  • 1
    Can I ask why you *don't* want to have a test database? – Sayse Jan 17 '16 at 20:27
  • 3
    @Sayse it is better to have independent unit tests, I don't want my tests to have a dependency on the database layer.If I rely on a database, I need to create the schema that django creates, populate it, etc. It will also be faster to run tests. – gire Jan 17 '16 at 20:35
  • @gire In a well designed code, you wouldn't encounter this problem. You might want to decouple your queries from the core logic and eliminate this issue. – khajvah Jan 17 '16 at 20:36
  • You definitely need database for testing, otherwise your test will bound do fail in the real environment. The dependency can be minimized if you use sqlite3 in-memory database settings. In this way you don't leave garbage in your system while testing as much as you can. http://stackoverflow.com/questions/3096148/how-to-run-djangos-test-database-only-in-memory?answertab=votes#tab-top – Shang Wang Jan 17 '16 at 20:49
  • 1
    @ShangWang > You definitely need database for testing, otherwise your test will bound do fail in the real environment. I think, that's a wrong statement. Unit tests should test one thing only. If the code piece is adding two numbers together, it doesn't matter if the numbers are from DB or not, test checks if those two numbers are correctly added and in order to speed up the tests, database should be eliminated from tests as much as possible. – khajvah Jan 17 '16 at 20:55
  • 1
    @khajvah Nah you misunderstood the situation. We are testing a web app, which is driven by data and logic not by logic itself. You example doesn't even fit in this discussion because there's no data involved. Django has `fixtures` and `Multi-database support` tops in their testing doc, why do you think they exist? https://docs.djangoproject.com/en/1.9/topics/testing/tools/#multi-database-support – Shang Wang Jan 17 '16 at 21:03
  • @ShangWang It doesn't matter what kind of application it is. The link you are referring is useful in some situations but when you are testing an `if..else` statement in an object, you don't need a database for it, even though you can't use that object without data. In that scenario, it's better to use tools like `mock` instead of firing up an entire database. Test databases, on the other hand, can be useful for testing the parts that directly work with the database, which should be the small part of your application. – khajvah Jan 17 '16 at 21:08
  • 2
    Any luck finding a solution to this problem? I'm encountering the same problem. – dsummersl Oct 21 '16 at 13:46

0 Answers0