2017-11-07 18 views
1

私の他の質問をお知りになりましたら、私はPythonで単体テストを行うのが非常に難しいことを知っています。努力の2日と私は進歩をしていない。Python Unit Test Mocking

私のクラスの一部であるメソッドでは、DALへの呼び出しがいくつかあります。

car_registration = self.dal.cars.get_by_registration('121D121') 

このDALは、基本クラスで構成されています。単体テストを実行しているときにこれらの呼び出しを完全にオーバーライド/モックして、あらかじめ定義された応答を返すようにして、メソッドを続行してすべてが期待通りに機能することを確認します。

での方法が開始:現時点で

def change_registration(self): 

    body = json.loads(self.request.body) 
    registration = body['registration'] 
    car = self.dal.cars.get_by_registration(registration) 

私のPythonのテストファイルは次のとおりです。

class CarTestCase(unittest.TestCase): 
    def setUp(self): 
     self.car_controller = CarController() 


    def test_change_registrations(self): 
     self.car_controller.dal.cars.get_by_registration = MagicMock(return_value=3) 
     response = self.car_controller.change_registration() 

私は応答3.しかし、エラーがスローされますことを期待しています。

AttributeError: 'CarController' object has no attribute '_py_object'

モックが動作していないと、それはまだユニットテストを使用している場合、完全に設定されていない主なDALを使用しようとして表示されます。実際のDALを探すのを防ぐためにどうすればよいのですか?

+0

を私はあなたが 'dal'属性を模擬する必要があると仮定します自体。 'self.car_controller.dal = Mock()'のようなものです。その後、 'self.car_controller.dal.cars.get_by_registration.return_value = 3'となります。 – chepner

+0

私がその行を変更した場合は、「AttributeError:属性を設定できません」というエラーが表示されます。 – user7692855

答えて

1

私はあなたが私達にあなたの戦略は何も問題がないため、エラーをトリガーするコードを示していないと思います。私たちは、私がこれを書くことができていない、それは問題なく実行されるコードを模倣するために、いくつかの想像力を使って:

import unittest 
from unittest.mock import MagicMock 

class CarList(): 
    def get_by_registration(self, registration): 
     pass 

class Dal: 
    def __init__(self): 
     self.cars = CarList() 
    pass 

class CarController: 

    def __init__(self): 
     self.dal = Dal() 

    def change_registration(self): 
     registration = None 
     car = self.dal.cars.get_by_registration(registration) 
     return car 

class CarTestCase(unittest.TestCase): 
    def setUp(self): 
     self.car_controller = CarController() 


    def test_change_registrations(self): 
     self.car_controller.dal.cars.get_by_registration =\ 
      MagicMock(return_value=3) 
     result = self.car_controller.change_registration() 
     self.assertEqual(result, 3) 

unittest.main() 
0

個人的意見:私はあなたが簡単に始めることをお勧めします。魔法以外の方法であなたが何を提供しているかを理解すれば、何か「魔法」を使用してください。非魔法の解決策を使用することは理解しやすい傾向があります。

私は、手元に複数の簡単な解決策があると思います。あなたが達成しようとした何のために、代わりの:

self.car_controller.dal.cars.get_by_registration = lambda: 3 
をしかし、あなたはすべてのメソッドを置き換えたい言及:

self.car_controller.dal.cars.get_by_registration = MagicMock(return_value=3) 

あなたは試みることができます。実際、私は「単純な」依存性注入を考えています。テストが難しい場合は、別のデザインが優れているという兆候かもしれません(これはTDD - テスト駆動設計のアイデアです)。単純な依存性注入は、たとえばdalをコンストラクタCarControllerに渡すだけです。ここで

は、テストのいくつかのバリエーションを持つ完全な例です:

​​
+0

MagicMockを使用した唯一の理由は、私はこれをどうやってやるべきかについて、まだ非常に混乱しています。私は自分を持つべきかどうか分からない。 CarControllerクラスのメンバであり、テストクラスではないためです。 – user7692855

+0

はい、インターネットには多くの例があります。私はあなたにいくつかのアイデアを与えるためにいくつかの簡単な例を追加しました。私は 'unittest'よりも' pytest'を好んでいます - 継承の必要はありません。しかしそれは細かいことだ。私はモックやマジックモックを使わないというわけではありません。しかし、なぜそれを使うべきかを理解するときにそれを使用してください。 – de1

+0

TestCaseクラスの中でselfを使うと、TestCaseではなくTestCaseを嘲笑しているように見えますが、self.car_controllerと書くと...これはCarControllerオブジェクトへの参照なので問題ありません。 – progmatico

0

ここに私の例:

# test_tool_file.py 
import unittest 

from unittest.mock import patch, Mock, call 

import test_tools_file 

class MyObject(): 
    def __init__(self, data): 
     self.data = data 

    def get_data(self): 
     return self.data 

    def count(self): 
     return len(self.get_data()) 

class TestFile(unittest.TestCase): 
    """ Cas de tests. 
    """ 
    @patch("test_tools_file.MyObject.get_data") 
    def test_1(self, mock_get): 
     """ test_1 
     """ 
     mock_get.return_value = [1,2,3,4,5,6] 

     obj = MyObject(["12", "13"]) 

     result = obj.count() 

     self.assertEqual(result, 6) 
関連する問題