Harici bir bloğu test etmek için bir İstisna oluşturmak için bir işlevle dalga geçmek


119

Başka bir işlevi ( foo) çağıran bir işlevim ( bar) var. Bir bar()yükseltirse HttpError, durum kodu 404 ise özel olarak ele almak, aksi takdirde yeniden yükseltmek istiyorum.

fooÇağrıyı alay ederek, bu işlev etrafında bazı birim testleri yazmaya çalışıyorum bar(). Maalesef, bloğum bar()tarafından yakalanan bir İstisna oluşturmak için alay edilen çağrıyı alamıyorum except.

İşte benim problemimi gösteren kodum:

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()

Hatayı alay işlevinin yükseltmesini sağlamak için bir örneği bir sınıfa ayarlamanız gerektiğini söyleyen Mock belgelerini takip ettim .side_effectMockException

Ayrıca, ilgili diğer bazı StackOverflow Soru ve Cevaplarına da baktım ve görünüşe göre onların alayları tarafından ortaya çıkmasına neden olmak için yaptıkları şeyi ve İstisna'yı yapıyorum.

Neden ayarlıyor side_effectarasında barMockbeklenen yol açmayan Exceptionyetiştirilmek üzere? Garip bir şey yapıyorsam, bloğumda mantığı test etmeye nasıl devam etmeliyim except?


Oldukça emin istisna değilim olduğunu ortaya atılan, ama emin sen ayarlarken nasıl değilim resp.statusorada kodu. Nereden HTTPErrorgeliyor?
Martijn Pieters

@MartijnPieters HttpErrortanımlanan bir sınıftır Google'ın apiclientlib biz GAE kullandığımız. O oluyor __init__parametreleri içeren tanımlanır (resp, content)Ben tepki için sahte bir örneğini oluşturmaya çalışırken bu yüzden uygun durum kodu belirtilmiş olan,.
Jesse Webb

Doğru, bu yüzden bu sınıf ; ama return_valueo zaman kullanıcıya gerek yok ; respvarlık değildir denir .
Martijn Pieters

1
Kodumu kullanmadan tekrar HttpErrordenedim ve bunun yerine normal bir Exceptionörnek kullanmayı denedim . Bu mükemmel çalışıyor. Bu, HttpErrorörneği nasıl yapılandırdığımla ilgili olması gerektiği anlamına gelir , muhtemelen Mockyanıt için nasıl örnek oluşturduğumla ilgilidir .
Jesse Webb

Yanıtlar:


141

Alayınız istisnayı gayet iyi yükseltiyor, ancak error.resp.statusdeğer eksik. Kullanmak yerine , bunun bir öznitelik olduğunu return_valuesöyleyin :Mockstatus

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

Mock()Ortaya çıkan nesnede öznitelikler olarak ayarlanacak ek anahtar sözcük bağımsız değişkenleri .

Sizin foove bartanımlarınızı bir my_testsmodüle koydum , HttpErrorsınıfa ekledim, böylece onu da kullanabilirim ve testiniz daha sonra başarıya götürülebilir:

>>> 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

Hatta print '404 - %s' % error.messagekoştuğunu bile görebilirsiniz , ama bence error.contentonun yerine orayı kullanmak istediniz ; bu HttpError(), her halükarda ikinci bağımsız değişkendeki öznitelik kümeleridir.


2
en side_effectönemli kısım
Daniel Butler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.