matobaの備忘録

和歌山と東京を往復しつつ活動するエンジニアの記録

unittest.mockの深い階層で迷う話

unittestのmockオブジェクトを使うときにいつも迷うのでメモ。

特に、深い階層にある何かをモックしようとすると、僕は今何をしてるんだろう、、、みたいな状況になったりする。

return_valueとかside_effectとかが混乱に原因になっているように思う。

例えば、こういうコードがあったとき。

from unittest import mock

a = mock.MagicMock(name='a mock')
b = mock.MagicMock(name='b mock')
b.return_value = a


print(b) # -> b mock

print(b()) # -> a mock

実行するとこうなる。

$ python3 mock_sample.py
<MagicMock name='b mock' id='4403051152'>
<MagicMock name='a mock' id='4400629128'>

以下は、b mockのMagicMockインスタンスが参照される。

print(b) # -> b mock  インスタンス

以下は、a mockのMagicMockインスタンスが参照される。

print(b()) # -> a mock インスタンス

こう書いて見ると当たり前なんだけど、なんか自分でコードを書いてるときに、当たり前のことがわからなくなる。

もう少し深いパターン

from unittest import mock

a = mock.MagicMock(name='a mock')
a.test.return_value = 'sample return value'
b = mock.MagicMock(name='b mock')
b.return_value = a

c = b()
print(c.test())
$ python3 mock_sample.py
sample return value

スッキリしたパターン

さっき書いたのは、冗長なので、スッキリさせる

from unittest import mock

b = mock.MagicMock(name='a mock')
b.return_value.test.return_value = 'sample return value'

c = b()
print(c.test())

結果は同じ。当たり前だけど、、、

$ python3 mock_sample.py
sample return value