2017-03-06 18 views
1

我正在使用MagicMock在Web應用程序中測試函數。該功能直接從模塊導入。當nosetest發現測試時,Magic Mock失敗

預期的行爲是:當被測試的函數被調用時,它調用第三方api(但我爲我的測試嘲笑這個)。這將返回一個字典,並將被測函數插入到一個對象中並返回該對象。

當我使用nosetests來運行特定的測試模塊時,這很好。

當我使用nosetests發現並運行我的test/unit/文件夾中的測試時,測試無法按預期工作。相反,模擬的API返回一個NoneType,並且正在測試的函數返回一個Magic Mock實例。

測試:

def test_get_user_facebook_data_1(self): 
    facebook_oauth_response = {u'name': u'Jack Jacker', u'email': u'[email protected]', u'id': u'sd5Jtvtk6'} 
    facepy.GraphAPI.get = MagicMock(return_value=facebook_oauth_response) 

    user_facebook_data = user_service.get_user_facebook_data('bogus_facebook_oauth_access_token') 

    self.assertEquals(user_facebook_data._facebook_oauth_id, u'sd5Jtvtk6') 
    self.assertEquals(user_facebook_data._email, u'[email protected]') 
    self.assertEquals(user_facebook_data._full_name, u'Jack Jacker') 

被測試(在user_service模塊)功能:

def get_user_facebook_data(facebook_access_token): 

    ''' 
    With a user's FB access token, retrieve their credentials to either create a new account or login. Create a user object from the user model,   but don't save 
    ''' 

    try: 
     graph = facepy.GraphAPI(facebook_access_token) 
     facebook_data = graph.get('me?fields=id,name,email') 
    except facepy.exceptions.OAuthError: 
     raise errors.FacebookAccessTokenInvalidError() 

    user = user_model.User() 

    try: 
     facebook_oauth_id = facebook_data[u'id'] 
     user.set_new_fb_oauth(facebook_oauth_id) 
    except KeyError: 
     raise errors.OauthNoIdError() 

    try: 
     email = facebook_data[u'email'] 
     user.set_new_email(email) 
    except KeyError: 
     pass 

    try: 
     full_name = facebook_data[u'name'] 
     user.set_new_full_name(full_name) 
    except KeyError: 
     pass 

    return user 

能否請你幫我理解爲什麼結果不一致?

編輯

新的信息 - 如果我直接在模塊上使用nosetests,我測試的函數訪問嘲笑Facepy字典值以Unicode(如預期)。如果我使用nosetests來發現測試,或者如果我使用下面的dm03514發佈的解決方案並直接運行測試,則該函數將從嘲笑的面部API作爲Magic Mock實例訪問字典。意思是,訪問該詞典的每個結果都是一個Magic Mock實例。

這很令人困惑,因爲我將return_value(在所有測試中)設置爲字典。

+0

更新回答:)測試是在類上修補'get'方法,而不是在實例上修補。該實例可以使用'return_value'引用 – dm03514

回答

2

對不起漫長的一天,所以不能真正精神上通過解析爲什麼事情正在他們目前是這樣:對

但事實如此執行,無論執行測試的地方以同樣的方式來解決這個問題,是patchfacepy導入user_service模塊。

def test_get_user_facebook_data_1(self): 
    facebook_oauth_response = {u'name': u'Jack Jacker', u'email': u'[email protected]', u'id': u'sd5Jtvtk6'} 
    with mock.patch('module.path.to.user_service.facepy') as mock_facepy: 
     mock_facepy.GraphAPI.return_vaule.get = MagicMock(return_value=facebook_oauth_response) 

     user_facebook_data = user_service.get_user_facebook_data('bogus_facebook_oauth_access_token') 

     self.assertEquals(user_facebook_data._facebook_oauth_id, u'sd5Jtvtk6') 
     self.assertEquals(user_facebook_data._email, u'[email protected]') 
     self.assertEquals(user_facebook_data._full_name, u'Jack Jacker') 

上述補丁facepy本地user_service模塊。

+0

我也試過這個,所以謝謝。這看起來像是嘲笑事物的巧妙方式,但是我的問題仍然存在(更新了我的問題)。 – JasTonAChair

+0

對不起,更新,忘記了返回值,現在應該工作。由於圖API正在被實例化,因此模擬需要一些如何指定你想修補的實例而不是類。 – dm03514

+0

所以,再次感謝。當我專門對這個模塊進行鼻子測試時,這確實奏效,但我的問題仍然是讓鼻子測試發現測試。無論如何,關於'return_value'的信息非常有用。 – JasTonAChair

0

我的問題是關於MagicMock處理字典的誤解。您需要聲明其__getitem__屬性。

我認爲我提到的「不一致性」更多地是我的測試工作的僥倖。

這很大程度上從@ dm03514的答案中借用。

def test_get_user_facebook_data_1(self): 
    facebook_oauth_response = {u'name': u'Jack Jacker', u'email': u'[email protected]', u'id': u'sd5Jtvtk6'} 
    with mock.patch('api.services.user_service.facepy') as mock_facepy: 

     # Mocking the response from the facepy. 
     # Setting this side effect allows the Mock object to be accessed as a dict. 
     def getitem(name): 
      return facebook_oauth_response[name] 
     mock_oauth = MagicMock() 
     mock_oauth.return_value = facebook_oauth_response 
     mock_oauth.__getitem__.side_effect = getitem 
     mock_facepy.GraphAPI.return_value.get = mock_oauth 

     user_facebook_data = user_service.get_user_facebook_data('bogus_facebook_oauth_access_token') 

     self.assertEquals(user_facebook_data._facebook_oauth_id, u'sd5Jtvtk6') 
     self.assertEquals(user_facebook_data._email, u'[email protected]') 
     self.assertEquals(user_facebook_data._full_name, u'Jack Jacker') 
相關問題