2020年1月31日 星期五

[Python] 測試中的mock patch技巧

  寫測試大家一定用過mock patch來做假資料,但有些程式碼乍看還真不知怎麼做patch,這裡我記錄了一些我遇過的例子,方便之後寫測試參考用。
  (P.S. 此篇不會說明pytest和mock用法,其實我常用的是pytest不是unittest) (會隨時更新)

1. 針對Context Manager  (就是用了with啦)

  欲測試func()這個函式,但在func裡面用到了KKK這個context manager,這時要怎麼patch這個物件呢? (實際上我遇到的是DB的context manager,在UT裡是不能用DB,所以這個一定要做mock)

func.py:
class KKK(object):
    def foo(self, x):
        return x
    def __enter__(self):
        print("enter")
        return self
    def __exit__(self, type, value, traceback):
        print("exit")

def func():
    res = 0
    with KKK() as k:
        res = res + k.foo(3)
    return res


測試:
from mock import patch, MagicMock
from func import func

def fake_func(x):
    return x + 1

class TestFunc():
    def setup(self):
        self.mock_kkk = patch("func.KKK").start()
        fake_kkk = MagicMock()
        fake_kkk.func.side_effect = fake_func
        self.mock_kkk.return_value.__enter__.return_value = fake_kkk

    def teardown(self):
        patch.stopall()

    def test_1(self):
        assert func() == 4

  這裡我會用MagicMock()建立一個假的物件,並為這個假的物件加上會在func()裡使用到的假函式,看是要單純的return_value直接丟固定值回來,或是要寫一個function來代替都可。
  重點是with KKK() as k,要讓這個k變成我建立的MagicMock fake_kkk,需要這樣寫「self.mock_kkk.return_value.__enter__.return_value = fake_kkk」




沒有留言:

張貼留言