2017-11-17 11 views
0

私は、リソースクラスのインスタンスを含むゲートウェイクラスを持っています。私はすでに、リソース上で私のユニットテストをやった、とテストを簡素化するために、リソースを初期化時に依存関係としてゲートウェイに注入されていますmocking注入クラスメソッド

class Gateway: 

    def __init__(self, resource): 
    self._resource = resource(Master) 

    def list_things(self): 
    return self._resource.list_resource() 

ゲートウェイがresource.list_resource()が呼び出されることを確認するために今私は、書き込みユニットテストを希望しますgateway.list_things()を呼び出した結果です。私の最高の試みは動作しません:

class TestGateway(unittest.TestCase): 

    def test_list_things(self): 
     mock_resource = Mock() 
     g = modbus.gateway.Gateway(mock_resource) 
     g.list_things() 
     mock_resource.list_resource.assert_called_once() 

結果:

AssertionError: Expected 'list_resource' to have been called once. Called 0 times. 

私は何をしないのですか?どのようなテストが期待することは、実際にチェックをエミュレートしているように、あなたのテストケースのためにGatewayに渡さmock_resourceの実際の使用例では

答えて

1

Gatewayでコンストラクタは、実際には、コンストラクタとしてresource引数へのさらなる呼び出しを行いますのメソッド呼び出しではなく、mock_resourceのインスタンスメソッドです。私はResourceのコンストラクタでself._resource = resource(Master)文をエミュレートするためself_resourceを割り当てられていた

>>> mock_resource = Mock() 
>>> self_resource = mock_resource('Master') # emulate Gateway.__init__ 
>>> self_resource.list_resource()   # emulate Gateway.list_things 
<Mock name='mock().list_resource()' id='140441464498496'> 
>>> mock_resource.list_resource.assert_called_once() # test_list_things 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.6/unittest/mock.py", line 795, in assert_called_once 
    raise AssertionError(msg) 
AssertionError: Expected 'list_resource' to have been called once. Called 0 times. 
>>> self_resource.list_resource.assert_called_once() # test the _actual_ call 
>>> 

注意し、あるもの対テストの不一致:文のこの使用してちょうど最小数は以下を使用して行うことができる実証実際に実行されたことが明らかになるはずです。この問題を解決するには

、テストがそうのようなコールチェックする必要があります:

def test_list_things(self): 
     mock_resource = Mock() 
     g = modbus.gateway.Gateway(mock_resource) 
     g.list_things() 
     # mock_resource.list_resource.assert_called_once() 
     g._resource.list_resource.assert_called_once() 
+0

を、私は、問題を分析するあなたのインタラクティブなアプローチに感謝 - ありがとうございました。あなたの答えは働きます(チェックマークがついています)が、 'g._resource'が呼び出されることだけをテストします。私がやったことは 'mock_resource = Mock()でした。 g._resource = mock_resource; g.list_things(); mock_resource.list_resource.assert_called_once() 'は、テストする意味の中心になります。 –

+0

@fearless_fool最終的な例の間違いであった 'g._resource.list_resource'をテストするつもりでした。私のポイントは最初の例の最後の行にまだ立っています。それにもかかわらず、私の本来の意図を反映するために、回答は更新されました。申し訳ありません。 – metatoaster

+1

また、これはまさに私が本当に嫌なものを使うことを嫌っている理由です。なぜなら、レーダーの下にある間違いを作るのは簡単すぎるからです。むしろ手動で構築するのは手間がかかりますが、エラーは簡単です見る。 – metatoaster