Djangoプロジェクトにユーティリティ関数があります。クエリセットを受け取り、そこからデータを取得して結果を返します。この関数のテストをいくつか作成したいと思います。とにかくQuerySetを「モック」しますか?データベースにアクセスしないオブジェクトを作成したいのですが、使用する値のリスト(つまり、いくつかの偽の行)を提供すると、クエリセットのように機能します。 、そして誰かがit/filter/get/allなどでフィールドルックアップを実行できるようにします。
このようなものはすでに存在しますか?
もちろん、QuerySetをモックすることも、何でもモックすることができます。
オブジェクトを自分で作成し、必要なインターフェイスを指定して、必要なデータを返すようにすることができます。本質的に、モックは、テストの目的のために本物のように十分に機能する「テストダブル」を提供することに他なりません。
始めるためのローテクな方法は、オブジェクトを定義することです。
class MockQuerySet(object):
pass
次に、これらの1つを作成し、テストに渡します。テストは失敗します。おそらくAttributeError
で失敗します。これにより、MockQuerySet
に何を実装する必要があるかがわかります。オブジェクトがテストに十分なリッチになるまで繰り返します。
私は同じ問題を抱えています、そして何人かの素敵な人がQuerySetsをモックするためのライブラリを書いたようです、それは mock-Django と呼ばれ、あなたが必要とする特定のコードはここにあります https: //github.com/dcramer/mock-Django/blob/master/mock_Django/query.py モデルオブジェクト関数にパッチを適用して、何かを返すように設定したこれらのQuerySetMockオブジェクトの1つを返すことができると思います期待!
空のクエリセットの場合、単純にnone
を keithhackbarthはすでに述べています として使用します。
ただし、値のリストを返すクエリセットをモックするには、モデルのマネージャーのspec
で モック を使用することをお勧めします。例として(Python 2.7スタイル- 外部モックライブラリを使用しました )、クエリセットをフィルタリングしてカウントする簡単なテストを次に示します。
from Django.test import TestCase
from mock import Mock
from .models import Example
def queryset_func(queryset, filter_value):
"""
An example function to be tested
"""
return queryset.filter(stuff=filter_value).count()
class TestQuerysetFunc(TestCase):
def test_happy(self):
"""
`queryset_func` filters provided queryset and counts result
"""
m_queryset = Mock(spec=Example.objects)
m_queryset.filter.return_value = m_queryset
m_queryset.count.return_value = 97
result = func_to_test(m_queryset, '__TEST_VALUE__')
self.assertEqual(result, 97)
m_queryset.filter.assert_called_once_with(stuff='__TEST_VALUE__')
m_queryset.count.assert_called_once_with()
ただし、質問を満たすために、count
にreturn_value
を設定する代わりに、これをlist
から返されるモデルインスタンスのall
に簡単に調整できます。
連鎖は、モックされたクエリセットを返すようにfilter
を設定することによって処理されることに注意してください。
m_queryset.filter.return_value = m_queryset
これは、テスト対象の関数で使用されるクエリセットメソッドに適用する必要があります。 exclude
など。
これには Djangoの.none()関数 を使用します。
例えば:
class Location(models.Model):
name = models.CharField(max_length=100)
mock_locations = Location.objects.none()
これは、Django独自の内部テストケースで頻繁に使用される方法です。コード内のコメントに基づく
Calling none() will create a queryset that never returns any objects and no
+query will be executed when accessing the results. A qs.none() queryset
+is an instance of ``EmptyQuerySet``.
FactoryBoyを調べましたか? https://factoryboy.readthedocs.io/en/latest/orms.html これはDjango ormをサポートするフィクスチャ交換ツールです-工場は基本的にormを生成します-オブジェクトのように(メモリ内またはテストデータベース内)。
始めるための素晴らしい記事は次のとおりです: https://www.caktusgroup.com/blog/2013/07/17/factory-boy-alternative-Django-testing-fixtures/
Django_mock_queries
library これにより、データベースアクセスをモックアウトし、フィルタリングなどのDjangoクエリセット機能の一部を引き続き使用できます。
完全な開示:私はプロジェクトにいくつかの機能を提供しました。
あなたはこのようにモックすることができます:
@patch('Django.db.models.query.QuerySet')
def test_returning_distinct_records_for_city(self, mock_qs):
self.assertTrue(mock_qs.called)