摘要:一些常用的示例先簡單定義個(gè)類,方便舉例這個(gè)類里有兩個(gè)成員方法,一個(gè)有參數(shù),一個(gè)無參數(shù)。有個(gè)模塊方法,返回?cái)?shù)據(jù)庫中所有指定的人員,并按排序掉整個(gè)數(shù)據(jù)庫訪問先得到一個(gè)的對象,再在中設(shè)置一個(gè)對象,此時(shí)不需要自己再創(chuàng)建
一些常用的mock示例
先簡單定義個(gè)類,方便舉例:
class Person: def __init__(self): self.__age = 10 def get_fullname(self, first_name, last_name): return first_name + " " + last_name def get_age(self): return self.__age @staticmethod def get_class_name(): return Person.__name__
這個(gè)類里有兩個(gè)成員方法,一個(gè)有參數(shù),一個(gè)無參數(shù)。還有一個(gè)靜態(tài)方法
class PersonTest(TestCase): def test_should_get_age(self): p = Person() # 不mock時(shí),get_age應(yīng)該返回10 self.assertEqual(p.get_age(), 10) # mock掉get_age方法,讓它返回20 p.get_age = Mock(return_value=20) self.assertEqual(p.get_age(), 20) def test_should_get_fullname(self): p = Person() # mock掉get_fullname,讓它返回"James Harden" p.get_fullname = Mock(return_value="James Harden") self.assertEqual(p.get_fullname(), "James Harden")
上面的例子你也許已經(jīng)注意到了,調(diào)用p.get_fullname時(shí)沒有給任何的參數(shù),但是依然可以工作。
如果想校驗(yàn)參數(shù)需要用create_autospec模塊方法替代Mock類。
class PersonTest(TestCase): def test_should_get_fullname(self): p = Person() p.get_fullname = create_autospec(p.get_fullname, return_value="James Harden") # 隨便給兩個(gè)參數(shù),依然會(huì)返回mock的值 self.assertEqual(p.get_fullname("1", "2"), "James Harden") # 如果參數(shù)個(gè)數(shù)不對,會(huì)報(bào)錯(cuò)TypeError: missing a required argument: "last_name" p.get_fullname("1")
class PersonTest(TestCase): def test_should_get_age(self): p = Person() p.get_age = Mock(side_effect=[10, 11, 12]) self.assertEqual(p.get_age(), 10) self.assertEqual(p.get_age(), 11) self.assertEqual(p.get_age(), 12)
class PersonTest(TestCase): def test_should_get_fullname(self): p = Person() values = {("James", "Harden"): "James Harden", ("Tracy", "Grady"): "Tracy Grady"} p.get_fullname = Mock(side_effect=lambda x, y: values[(x, y)]) self.assertEqual(p.get_fullname("James", "Harden"), "James Harden") self.assertEqual(p.get_fullname("Tracy", "Grady"), "Tracy Grady")
class PersonTest(TestCase): def test_should_raise_exception(self): p = Person() p.get_age = Mock(side_effect=TypeError("integer type")) # 只要調(diào)就會(huì)拋出異常 self.assertRaises(TypeError, p.get_age)
class PersonTest(TestCase): def test_should_validate_method_calling(self): p.get_fullname = Mock(return_value="James Harden") # 沒調(diào)用過 p.get_fullname.assert_not_called() # Python 3.5 p.get_fullname("1", "2") # 調(diào)用過任意次數(shù) p.get_fullname.assert_called() # Python 3.6 # 只調(diào)用過一次, 不管參數(shù) p.get_fullname.assert_called_once() # Python 3.6 # 只調(diào)用過一次,并且符合指定的參數(shù) p.get_fullname.assert_called_once_with("1", "2") p.get_fullname("3", "4") # 只要調(diào)用過即可,必須指定參數(shù) p.get_fullname.assert_any_call("1", "2") # 重置mock,重置之后相當(dāng)于沒有調(diào)用過 p.get_fullname.reset_mock() p.get_fullname.assert_not_called() # Mock對象里除了return_value, side_effect屬性外, # called表示是否調(diào)用過,call_count可以返回調(diào)用的次數(shù) self.assertEqual(p.get_fullname.called, False) self.assertEqual(p.get_fullname.call_count, 0) p.get_fullname("1", "2") p.get_fullname("3", "4") self.assertEqual(p.get_fullname.called, True) self.assertEqual(p.get_fullname.call_count, 2)mock靜態(tài)方法
靜態(tài)方法和模塊方法需要使用patch來mock。
class PersonTest(TestCase): # 以字符串的形式列出靜態(tài)方法的路徑,在測試的參數(shù)里會(huì)自動(dòng)得到一個(gè)Mock對象 @patch("your.package.module.Person.get_class_name") def test_should_get_class_name(self, mock_get_class_name): mock_get_class_name.return_value = "Guy" self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): mock_get_class_name = Mock(return_value="Guy") # 在patch中給出定義好的Mock的對象,好處是定義好的對象可以復(fù)用 @patch("your.package.module.Person.get_class_name", mock_get_class_name) def test_should_get_class_name(self): self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): mock_get_class_name = Mock(return_value="Guy") # 使用patch.object來mock,好處是Person類不是以字符串形式給出的 @patch.object(Person, "get_class_name", mock_get_class_name) def test_should_get_class_name(self, ): self.assertEqual(Person.get_class_name(), "Guy")
class PersonTest(TestCase): # 作用域之外,依然返回真實(shí)值 def test_should_get_class_name(self, ): mock_get_class_name = Mock(return_value="Guy") with patch("your.package.module.Person.get_class_name", mock_get_class_name): self.assertEqual(Person.get_class_name(), "Guy") self.assertEqual(Person.get_class_name(), "Person")mock鏈?zhǔn)秸{(diào)用
在django里,我們經(jīng)常需要mock數(shù)據(jù)庫,而訪問數(shù)據(jù)庫時(shí)經(jīng)常是鏈?zhǔn)秸{(diào)用,看個(gè)例子。
def get_person(name): return Person.objects.filter(name=name).order_by("age")
有個(gè)模塊方法,返回?cái)?shù)據(jù)庫中所有指定name的人員,并按age排序
mock掉整個(gè)數(shù)據(jù)庫訪問
@patch("your.package.module.Person.objects.filter") def test_should_get_person(self, mock_filter): # 先得到一個(gè)filter的Mock對象,再在return_value中設(shè)置一個(gè)Mock對象,此時(shí)不需要自己再創(chuàng)建 mock_filter.return_value.order_by.return_value = None self.assertIsNone(get_person())
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45535.html
摘要:每個(gè)測試方法的名稱以單詞開頭,單元測試是如何識別它們是測試的。它還意味著知道測試文件中有多少單元測試,而不是簡單地知道有多少表達(dá)式您可能已經(jīng)注意到將每個(gè)行作為單獨(dú)的測試計(jì)數(shù)。 showImg(https://segmentfault.com/img/remote/1460000019140153); 來源 | 愿碼(ChainDesk.CN)內(nèi)容編輯 愿碼Slogan | 連接每個(gè)程...
摘要:準(zhǔn)確的說,是中一個(gè)用于支持單元測試的庫,它的主要功能是使用對象替代掉指定的對象,以達(dá)到模擬對象的行為。下面我們使用對象在單元測試中分別測試訪問正常和訪問不正常的情況。 Mock是什么 Mock這個(gè)詞在英語中有模擬的這個(gè)意思,因此我們可以猜測出這個(gè)庫的主要功能是模擬一些東西。準(zhǔn)確的說,Mock是Python中一個(gè)用于支持單元測試的庫,它的主要功能是使用mock對象替代掉指定的Python...
摘要:接下來我們將介紹如何對對象的方法進(jìn)行模擬測試。選項(xiàng)創(chuàng)建模擬測試接口我們可以在的構(gòu)造函數(shù)中提供一個(gè)模擬測試實(shí)例,而不是模擬創(chuàng)建具體的模擬測試方法。 如何不靠耐心測試 通常,我們編寫的軟件會(huì)直接與那些我們稱之為骯臟的服務(wù)交互。通俗地說,服務(wù)對我們的應(yīng)用來說是至關(guān)重要的,它們之間的交互是我們設(shè)計(jì)好的,但這會(huì)帶來我們不希望的副作用——就是那些在我們自己測試的時(shí)候不希望的功能。 比如,可能我們...
摘要:也就是說,如果不需要,兩者使用起來并沒有什么分別。來看個(gè)例子,先定義個(gè)類,里面只有一個(gè)成員方法,返回倍的數(shù)值使用類來掉這個(gè)成員方法使用類來兩者沒有任何區(qū)別,都成功了了成員方法。再看下兩者的區(qū)別因?yàn)槭褂妙悤r(shí),默認(rèn)不會(huì)創(chuàng)建這個(gè)的,所以報(bào)錯(cuò)。 Python的unittest.mock模塊中提供了兩個(gè)主要的mock類,分別是Mock和MagicMock. 先看一下官方文檔的定義: MagicM...
閱讀 2326·2021-11-17 09:33
閱讀 852·2021-10-13 09:40
閱讀 582·2019-08-30 15:54
閱讀 788·2019-08-29 15:38
閱讀 2423·2019-08-28 18:15
閱讀 2481·2019-08-26 13:38
閱讀 1848·2019-08-26 13:36
閱讀 2137·2019-08-26 11:36