Je teste en unité une classe qui utilise peewee pour ORM. J'ai utilisé mock pour le test et j'ai essayé de vérifier si la valeur correcte était définie pour l'attribut du modèle, mais ce que j'ai défini pour l'attribut dans le constructeur du modèle Lors du passage en argument avec un mot-clé, la classe mock.Mock n'a pas pu être testée correctement telle quelle, j'ai donc créé une simulation qui définit l'argument avec un mot-clé sur un attribut.
Je n'ai que deux mois en Python, et j'ai peut-être fait une grosse erreur, et il y a peut-être un moyen plus intelligent de le faire. Si quelqu'un connaît des erreurs ou de meilleures façons, il serait grandement apprécié que vous puissiez commenter.
PostScript 15/10/2016 Le code de cet article ne prend en charge que le cas où une seule maquette est créée. Dans le cas d'instanciations multiples, vous devez utiliser une méthode comme @ podhmo's Example code dans le commentaire.
$ pip install peewee
$ pip install mock
$ tree
.
├── src
│ ├── __init__.py
│ ├── model.py
│ └── service.py
└── test
├── __init__.py
└── test_service.py
src/service.py
# -*- coding: utf-8 -*-
from model import HogeModel
class HogeService(object):
def run(self):
model = HogeModel(name='hoge name')
model.desc = 'hoge desc'
model.save()
src/model.py
# -*- coding: utf-8 -*-
from peewee import SqliteDatabase
from peewee import Model
from peewee import PrimaryKeyField
from peewee import CharField
db = SqliteDatabase('hoge.db')
class HogeModel(Model):
id = PrimaryKeyField
name = CharField()
desc = CharField()
class Meta:
database = db
test/test_service.py
# -*- coding: utf-8 -*-
import unittest
from mock import patch
from mock import Mock
from service import HogeService
class TestHogeService(unittest.TestCase):
@patch('service.HogeModel')
def test_run(self, mock_hoge_model):
mock = Mock()
mock_hoge_model.return_value = mock
target = HogeService()
target.run()
self.assertEquals(1, mock.save.call_count) # OK
self.assertEquals('hoge desc', mock.desc) # OK
self.assertEquals('hoge name', mock.name) # NG
if __name__ == '__main__':
unittest.main()
$ PYTHONPATH=src python test/test_service.py
F
======================================================================
FAIL: test_run (__main__.TestHogeService)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/otti/.pyenv/versions/2.7.12/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "test/test_service.py", line 18, in test_run
self.assertEquals('hoge name', mock.name) # NG
AssertionError: 'hoge name' != <Mock name='HogeModel().name' id='4454023888'>
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
model = HogeModel (name = 'hoge name')
dans service.HogeService n'est pas défini dans l'attribut simulé.test/test_service.py
# -*- coding: utf-8 -*-
import unittest
from mock import Mock
from mock import patch
from service import HogeService
class TestHogeService(unittest.TestCase):
def create_attr_set_mock(self, **kwargs):
self.mock = Mock()
#Définissez l'argument mot-clé passé dans le constructeur sur l'attribut
for k, v in kwargs.items():
self.mock.__dict__[k] = v
return self.mock
@patch('service.HogeModel')
def test_run(self, mock_hoge_model):
#Renvoie une simulation qui définit un attribut avec un argument de mot-clé dans le constructeur lors de l'instanciation de la classe cible
mock_hoge_model.side_effect = lambda **kwargs: self.create_attr_set_mock(**kwargs)
target = HogeService()
target.run()
self.assertEquals(1, self.mock.save.call_count) # OK
self.assertEquals('hoge desc', self.mock.desc) # OK
self.assertEquals('hoge name', self.mock.name) # OK
if __name__ == '__main__':
unittest.main()
PYTHONPATH=src python test/test_service.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Vous avez maintenant une maquette du modèle qui fonctionne comme prévu. C'était un peu déroutant car mock.Mock semble avoir un attribut appelé name en premier lieu, mais c'était la même chose même si je l'ai essayé avec des attributs autres que name.
Recommended Posts