Reputation: 25542
Here is my Python method:
for time in (timedelta(hours=3), timedelta(minutes=30)):
delay = (datetime.now() + time).strftime('%Y-%m-%dT%H:%M:%S')
payload = json.dumps({
"channels": [
"accountID-{acct_id}".format(acct_id=account_id)
],
"push_time": delay,
"data": {
"alert": "Test Push",
"m": "12345"
},
})
try:
requests.post(
"https://api.parse.com/1/push",
data=payload,
headers={
"X-Parse-Application-Id": settings.PARSE_APPLICATION_ID,
"X-Parse-REST-API-Key": settings.PARSE_REST_API_KEY,
"Content-Type": "application/json"
}
)
except requests.exceptions.RequestException as e:
logging.getLogger().setLevel(logging.ERROR)
Here is my test:
@patch("requests.post")
def test_send_push_notifications_to_parse(self, post_mock):
post_mock.return_value = {"status": 200}
mailing = Mock()
mailing.name = "Foo Name"
mailing.account_id = 12345
mailing.mailing_id = 45
payload = json.dumps({
"channels": [
"accountID-12345"
],
"push_time": "2014-03-04T15:00:00",
"data": {
"alert": "Test Push",
"m": "12345"
},
})
send_push_notification_to_parse(mailing.account_id, mailing.mailing_id, mailing.name)
post_mock.assert_called_with(
"https://api.parse.com/1/push",
data=payload,
headers={
"X-Parse-Application-Id": settings.PARSE_APPLICATION_ID,
"X-Parse-REST-API-Key": settings.PARSE_REST_API_KEY,
"Content-Type": "application/json"
}
)
The test fails because the POST request is inside of a loop where the datetime
object changes. How can I patch the datetime
object to make my test pass?
Upvotes: 1
Views: 3062
Reputation: 620
Anyone stumbling on this old question like me can use freezegun that Lets your Python tests travel through time(like Interstellar:))
Upvotes: 0
Reputation: 1121914
Just mock datetime
in your module:
@patch("your.module.datetime")
@patch("requests.post")
def test_send_push_notifications_to_parse(self, post_mock, dt_mock):
# set datetime.now() to a fixed value
dt_mock.now.return_value = datetime.datetime(2013, 2, 1, 10, 9, 8)
You bound datetime
in your module with an import, and the above @patch
decorator will replace that object with a mock.
If you need to test against multiple values, you can set the dt_mock.now.side_effect
attribute instead; a list will cause the mock to return values one by one from that list on sequential calls, a method lets you produce a new value each time datetime.now()
is called as needed.
Upvotes: 3