2015-02-03 19 views
42

Tôi có một chức năng (foo) gọi một chức năng khác (bar). Nếu gọi bar() tăng HttpError, tôi muốn xử lý nó đặc biệt nếu mã trạng thái là 404, nếu không thì sẽ tăng.Mocking một chức năng để nâng một ngoại lệ để kiểm tra một khối ngoại trừ

Tôi đang cố gắng viết một số bài kiểm tra đơn vị xung quanh chức năng foo này, nhổ cuộc gọi đến bar(). Rất tiếc, tôi không thể nhận cuộc gọi nhạo báng đến số bar() để tăng ngoại lệ bị chặn bởi khối except của tôi.

Đây là mã của tôi mà minh họa vấn đề của tôi:

import unittest 
import mock 
from apiclient.errors import HttpError 


class FooTests(unittest.TestCase): 
    @mock.patch('my_tests.bar') 
    def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock): 
     barMock.return_value = True 
     result = foo() 
     self.assertTrue(result) # passes 

    @mock.patch('my_tests.bar') 
    def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock): 
     barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found') 
     result = foo() 
     self.assertIsNone(result) # fails, test raises HttpError 

    @mock.patch('my_tests.bar') 
    def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock): 
     barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error') 
     with self.assertRaises(HttpError): # passes 
      foo() 

def foo(): 
    try: 
     result = bar() 
     return result 
    except HttpError as error: 
     if error.resp.status == 404: 
      print '404 - %s' % error.message 
      return None 
     raise 

def bar(): 
    raise NotImplementedError() 

Tôi làm theo các Mock docs mà nói rằng bạn nên thiết lập các side_effect của một trường hợp Mock để một lớp Exception để có chức năng chế giễu nâng cao lỗi.

Tôi cũng đã xem xét một số StackOverflow khác có liên quan Q & Như, và có vẻ như tôi đang làm điều tương tự mà chúng đang làm để gây ra và Ngoại lệ được nâng lên bởi mô hình của chúng.

Tại sao thiết lập side_effect của barMock không gây ra dự kiến ​​Exception được nâng lên? Nếu tôi đang làm điều gì đó kỳ lạ, làm thế nào tôi nên đi về thử nghiệm logic trong khối except của tôi?

+0

Tôi khá chắc chắn ngoại lệ của bạn * đang được nâng lên, nhưng tôi không chắc chắn cách bạn đang đặt mã 'resp.status' ở đó. 'HTTPError' xuất phát từ đâu? –

+0

@MartijnPieters 'HttpError' là một lớp được định nghĩa trong [lib' libiclient' của Google] (https://developers.google.com/api-client-library/python/) mà chúng tôi sử dụng trong GAE. Đó là '__init__' được định nghĩa với các tham số' (resp, content) 'vì vậy tôi đã cố tạo một cá thể giả cho đáp ứng, với mã trạng thái thích hợp được chỉ định. –

+0

Phải, vậy là [lớp này] (https://github.com/google/google-api-python-client/blob/master/googleapiclient/errors.py#L35-L63); nhưng bạn không cần phải sử dụng 'return_value' rồi; 'resp' không được * gọi là *. –

Trả lời

54

Mô hình của bạn đang tăng ngoại lệ tốt, nhưng thiếu giá trị error.resp.status. Thay vì sử dụng return_value, chỉ nói rằng Mockstatus là một thuộc tính:

barMock.side_effect = HttpError(mock.Mock(status=404), 'not found') 

đối số từ khóa bổ sung để Mock() được thiết lập như là thuộc tính trên đối tượng kết quả.

tôi đặt foobar bạn định nghĩa trong một module my_tests, bổ sung trong HttpError class vì vậy tôi có thể sử dụng nó quá, và thử nghiệm của bạn sau đó có thể được chạy đến thành công:

>>> from my_tests import foo, HttpError 
>>> import mock 
>>> with mock.patch('my_tests.bar') as barMock: 
...  barMock.side_effect = HttpError(mock.Mock(status=404), 'not found') 
...  result = my_test.foo() 
... 
404 - 
>>> result is None 
True 

Bạn thậm chí có thể nhìn thấy print '404 - %s' % error.message dòng chạy, nhưng tôi nghĩ bạn muốn sử dụng error.content ở đó thay thế; đó là thuộc tính HttpError() bộ từ đối số thứ hai, ở bất kỳ tỷ lệ nào.

+0

Điều này đã làm các trick, cảm ơn bạn! –

Các vấn đề liên quan