我在理解模拟如何工作以及如何使用模拟对象编写单元测试时遇到问题。我想模拟一个外部api调用,这样我就可以为这些使用这些调用的函数和函数编写单元测试。
我首先尝试模拟check_sms_request,然后我需要用它做一些事情来覆盖对象的check_delivery_status。
如何为这种情况编写测试?
模拟
的功能def check_sms_request(remote_id, phone):
if not can_sms(phone):
return None
client = Client(settings.SMS_API_URL)
base_kwargs = {
'phone': phone,
'remoteId': remote_id,
}
request = client.service.CheckSmsRequest(settings.SMS_API_LOGIN, settings.SMS_API_PASSWORD, base_kwargs)
return request
class SMS(models.Model):
sms_response = models.IntegerField(choices=SMS_SEND_STATUS, null=True, blank=True)
delivery_status = models.IntegerField(choices=DELIVERY_STATUS_CHOICES, null=True, blank=True)
has_final_status = models.BooleanField(default=False)
def check_delivery_status(self):
if not self.has_final_status:
response_status = check_sms_request(self.id, self.phone)
if response_status is not None:
self.history.create(fbs_status=self.sms_response, delivery_status=response_status.response)
if response_status is not None and response_status.response in FINAL_STATUSES:
self.has_final_status = True
if response_status is not None:
self.delivery_status = response_status.response
self.save()
return self.delivery_status
我的测试:
@override_settings(SMS_WHITELIST=['', ], SMS_ENABLE=True)
def test_soap_check_sms_request(self):
check_sms_request = Mock(return_value=True)
check_sms_request.response = SMS_SENT_AND_RECIEVED
self.assertEqual(check_sms_request.response, SMS_SENT_AND_RECIEVED)
obj = SMS.objects.create(**{
'phone': self.user.phone,
'text': u"Hello",
'user': self.user,
'site': self.site2,
})
obj.check_sms_status()
答案 0 :(得分:0)
您可以对测试功能进行猴子修补,如下所示:
@override_settings(SMS_WHITELIST=['', ], SMS_ENABLE=True)
def test_soap_check_sms_request(self):
check_sms_request = Mock(return_value=True)
check_sms_request.response = SMS_SENT_AND_RECIEVED
self.assertEqual(check_sms_request.response, SMS_SENT_AND_RECIEVED)
obj = SMS.objects.create(**{
'phone': self.user.phone,
'text': u"Hello",
'user': self.user,
'site': self.site2,
})
import model
old_fn = model.check_sms_request
model.check_sms_request = check_sms_request
obj.check_sms_status()
model.check_sms_request = old_fn
答案 1 :(得分:0)
型号:
class SMS(models.Model):
sms_response = models.IntegerField(choices=SMS_SEND_STATUS, null=True, blank=True)
delivery_status = models.IntegerField(choices=DELIVERY_STATUS_CHOICES, null=True, blank=True)
has_final_status = models.BooleanField(default=False)
def check_sms_request(remote_id, phone):
if not can_sms(phone):
return None
client = Client(settings.SMS_API_URL)
base_kwargs = {
'phone': phone,
'remoteId': remote_id,
}
request = client.service.CheckSmsRequest(settings.SMS_API_LOGIN, settings.SMS_API_PASSWORD, base_kwargs)
return request
def check_delivery_status(self):
if not self.has_final_status:
response_status = self.check_sms_request(self.id, self.phone)
if response_status is not None:
self.history.create(fbs_status=self.sms_response, delivery_status=response_status.response)
if response_status is not None and response_status.response in FINAL_STATUSES:
self.has_final_status = True
if response_status is not None:
self.delivery_status = response_status.response
self.save()
return self.delivery_status
测试:
class SMSModelTestCase(TestCase):
@patch('...Client')
def test_check_sms_request(self, ClientMock):
client_object = ClientMock.return_value
CheckSmsRequestMock = client_object.service.return_value.CheckSmsRequest
sms_model = SMS() # don't save
with self.settings(SMS_API_URL='http://example.com', SMS_API_LOGIN='kanata', SMS_API_PASSWORD='izumi'):
sms_model.check_sms_request(101, '+11111111')
ClientMock.assert_called_once_with('http://example.com')
CheckSmsRequestMock.assert_called_once_with('kanata', 'izumi', '+11111111', 101)
@patch('myproject.myapp.models.SMS.check_sms_request')
def test_check_delivery_status(self, CheckSmsRequestMock):
CheckSmsRequestMock.return_value = ...
sms_model = SMS()
...
sms_model.check_delivery_status(...)