mox and datetime

168 views
Skip to first unread message

Vbabiy

unread,
Jun 14, 2009, 10:49:01 PM6/14/09
to mox-discuss
How I am trying to mock out the datetime.now method, but I can't seem
to do it right. Can someone give me an example.

Thanks

Vitaly Babiy

unread,
Jun 14, 2009, 10:59:12 PM6/14/09
to mox-discuss
This is the error i am getting:

Traceback (most recent call last):
  File "/home/vbabiy/projects/git-projects/howsthedotcom/accounts/tests/send_email_verification.py", line 14, in tearDown
    self.mox.UnsetStubs()
  File "/var/lib/python-support/python2.6/mox.py", line 230, in UnsetStubs
    self.stubs.UnsetAll()
  File "/var/lib/python-support/python2.6/stubout.py", line 136, in UnsetAll
    setattr(parent, child_name, old_child)
TypeError: can't set attributes of built-in/extension type 'datetime.datetime'


Vitaly Babiy

David Glasser

unread,
Jun 14, 2009, 11:01:07 PM6/14/09
to mox-d...@googlegroups.com

Steve, this is probably the most frequently asked question, maybe it should go in some FAQ!

Answers include "mock out datetime.datetime" and "make the original code get the time via another method that can be mocked out or via a default argument def foo(now=datetime.datetime.now) which can be overridden".

--dave

steve middlekauff

unread,
Jun 14, 2009, 11:04:42 PM6/14/09
to mox-d...@googlegroups.com
Ha, I was _just_ re-looking through some of the other threads on this
topic. I'll add it to the FAQ tomorrow.
--
Steve Middlekauff
smid...@gmail.com

Vitaly Babiy

unread,
Jun 16, 2009, 9:44:28 PM6/16/09
to mox-d...@googlegroups.com
Thanks, Look forward to reviewing the FAQ
Vitaly Babiy

steve middlekauff

unread,
Jun 18, 2009, 3:56:56 PM6/18/09
to mox-d...@googlegroups.com
Sorry for the delay on this! D:

I just added a quick example to the recipes page:
http://code.google.com/p/pymox/wiki/MoxRecipes
--
Steve Middlekauff
smid...@gmail.com

Vbabiy

unread,
Jun 19, 2009, 4:38:36 PM6/19/09
to mox-discuss
Awesome thanks alot steve

On Jun 18, 3:56 pm, steve middlekauff <smidd...@gmail.com> wrote:
> Sorry for the delay on this! D:
>
> I just added a quick example to the recipes page:http://code.google.com/p/pymox/wiki/MoxRecipes
>
>
>
> On Tue, Jun 16, 2009 at 6:44 PM, Vitaly Babiy<vbabi...@gmail.com> wrote:
> > Thanks, Look forward to reviewing the FAQ
> > Vitaly Babiy
>
> > On Sun, Jun 14, 2009 at 11:04 PM, steve middlekauff <smidd...@gmail.com>
> > wrote:
>
> >> Ha, I was _just_ re-looking through some of the other threads on this
> >> topic.  I'll add it to the FAQ tomorrow.
>
> >> On Sun, Jun 14, 2009 at 8:01 PM, David Glasser<glas...@davidglasser.net>
> >> wrote:
> >> > Steve, this is probably the most frequently asked question, maybe it
> >> > should
> >> > go in some FAQ!
>
> >> > Answers include "mock out datetime.datetime" and "make the original code
> >> > get
> >> > the time via another method that can be mocked out or via a default
> >> > argument
> >> > def foo(now=datetime.datetime.now) which can be overridden".
>
> >> > --dave
>
> >> > On Jun 14, 2009 7:49 PM, "Vbabiy" <vbabi...@gmail.com> wrote:
>
> >> > How I am trying to mock out the datetime.now method, but I can't seem
> >> > to do it right. Can someone give me an example.
>
> >> > Thanks
>
> >> --
> >> Steve Middlekauff
> >> smidd...@gmail.com
>
> --
> Steve Middlekauff
> smidd...@gmail.com

Vbabiy

unread,
Jun 19, 2009, 4:48:57 PM6/19/09
to mox-discuss
So same issue, Can some help me understand which method is not mocked
out

Traceback (most recent call last):
File "/home/vbabiy/projects/git-projects/howsthedotcom/accounts/
tests/send_email_verification.py", line 27, in test_find
self.assertEquals(com.handle(), date)
File "/home/vbabiy/projects/git-projects/howsthedotcom/accounts/
management/commands/send_email_verification.py", line 12, in handle
evs = EmailVerification.objects.filter
(last_sent_at__lte=check_date)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/
manager.py", line 129, in filter
return self.get_query_set().filter(*args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/
query.py", line 498, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/
query.py", line 516, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/
query.py", line 1675, in add_q
can_reuse=used_aliases)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/
query.py", line 1614, in add_filter
connector)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/
where.py", line 56, in add
obj, params = obj.process(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/
where.py", line 269, in process
params = self.field.get_db_prep_lookup(lookup_type, value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/
__init__.py", line 507, in get_db_prep_lookup
return super(DateField, self).get_db_prep_lookup(lookup_type,
value)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/
__init__.py", line 210, in get_db_prep_lookup
return [self.get_db_prep_value(value)]
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/
__init__.py", line 569, in get_db_prep_value
return connection.ops.value_to_db_datetime(self.to_python(value))
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/
__init__.py", line 533, in to_python
if isinstance(value, datetime.datetime):
File "/var/lib/python-support/python2.6/mox.py", line 414, in
__getattr__
raise UnknownMethodCallError(name)
UnknownMethodCallError: Method called is not a member of the object:
__bases__



On Jun 18, 3:56 pm, steve middlekauff <smidd...@gmail.com> wrote:
> Sorry for the delay on this! D:
>
> I just added a quick example to the recipes page:http://code.google.com/p/pymox/wiki/MoxRecipes
>
>
>
> On Tue, Jun 16, 2009 at 6:44 PM, Vitaly Babiy<vbabi...@gmail.com> wrote:
> > Thanks, Look forward to reviewing the FAQ
> > Vitaly Babiy
>
> > On Sun, Jun 14, 2009 at 11:04 PM, steve middlekauff <smidd...@gmail.com>
> > wrote:
>
> >> Ha, I was _just_ re-looking through some of the other threads on this
> >> topic.  I'll add it to the FAQ tomorrow.
>
> >> On Sun, Jun 14, 2009 at 8:01 PM, David Glasser<glas...@davidglasser.net>
> >> wrote:
> >> > Steve, this is probably the most frequently asked question, maybe it
> >> > should
> >> > go in some FAQ!
>
> >> > Answers include "mock out datetime.datetime" and "make the original code
> >> > get
> >> > the time via another method that can be mocked out or via a default
> >> > argument
> >> > def foo(now=datetime.datetime.now) which can be overridden".
>
> >> > --dave
>
> >> > On Jun 14, 2009 7:49 PM, "Vbabiy" <vbabi...@gmail.com> wrote:
>
> >> > How I am trying to mock out the datetime.now method, but I can't seem
> >> > to do it right. Can someone give me an example.
>
> >> > Thanks
>
> >> --
> >> Steve Middlekauff

David Glasser

unread,
Jun 19, 2009, 4:50:57 PM6/19/09
to mox-d...@googlegroups.com
Can you show your code?

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

Vbabiy

unread,
Jun 19, 2009, 5:25:44 PM6/19/09
to mox-discuss
Sure,

def handle(self, now=datetime.now(), *args, **kargs):
# Delete all Email Verification that are over 30 days old
check_date = now - timedelta(days=30)
evs = EmailVerification.objects.filter
(last_sent_at__lte=check_date)
print "Deleting %d Email Verification that are prior to %s" %
(len(evs), str(check_date))
for ev in evs:
ev.delete()
> glas...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

David Glasser

unread,
Jun 19, 2009, 5:31:44 PM6/19/09
to mox-d...@googlegroups.com
So two issues: first, "datetime.now" is not the same as
"datetime.datetime.now". But more importantly, you do realize that
this will call datetime.now() only once, handle is called, and "now"
will be fixed after that, right?

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

Vbabiy

unread,
Jun 19, 2009, 5:38:00 PM6/19/09
to mox-discuss
Sorry i sent you the wrong code :(
import datetime
....
def handle(self, *args, **kargs):
# Delete all Email Verification that are over 30 days old
check_date = datetime.datetime.now() - datetime.timedelta
(days=30)
evs = EmailVerification.objects.filter
(last_sent_at__lte=check_date)
print "Deleting %d Email Verification that are prior to %s" %
(len(evs), str(check_date))
for ev in evs:
ev.delete()

> glas...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

David Glasser

unread,
Jun 19, 2009, 5:42:30 PM6/19/09
to mox-d...@googlegroups.com
OK, and the test code?

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

Vbabiy

unread,
Jun 19, 2009, 5:50:16 PM6/19/09
to mox-discuss

class SendEmailCommandTestCase(TestCase):
""" Test case to test send verifications email command """

def setUp(self):
self.mox = mox.Mox()

def tearDown(self):
self.mox.UnsetStubs()
self.mox.VerifyAll()

def test_find(self):
date = datetime.datetime(2009,1,1)

self.mox.StubOutWithMock(datetime.datetime,"now")
datetime.datetime.now().AndReturn(date)

self.mox.ReplayAll()


handle()
> glas...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

David Glasser

unread,
Jun 19, 2009, 5:55:02 PM6/19/09
to mox-d...@googlegroups.com
Please look at the FAQ entry: you need to be stubbing out the
"datetime" field of the datetime module, not the "now" field of the
datetime.datetime class.

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

Vitaly Babiy

unread,
Jun 19, 2009, 10:23:31 PM6/19/09
to mox-d...@googlegroups.com
Hey still same error:

Test:
from django.test import TestCase
import datetime
import mox
from accounts.management.commands.send_email_verification import Command
from accounts.models import EmailVerification
from django.core import mail


class SendEmailCommandTestCase(TestCase):
    """ Test case to test send verifications email command """
    
    fixtures = [
        'billing',
        'auth',
        'accounts',
        'email_verification'
    ]
    
    def setUp(self):
        self.mox = mox.Mox()
    
    def tearDown(self):
        self.mox.UnsetStubs()
        self.mox.VerifyAll()
    
    def test_mox(self):
        # Prep for test
        date = datetime.datetime(2009,1,1,1,1,1)
        
        self.mox.StubOutWithMock(datetime, 'datetime')
        datetime.datetime.now().AndReturn(date)
        self.mox.ReplayAll()
        com = Command()
        com.handle()

Code:
from django.core.management.base import BaseCommand
import datetime
from accounts.models import EmailVerification

class Command(BaseCommand):
    help = 'Resend email to accounts that have not been verified in 2 weeks, also remove email verification that are more the 30 days.'

    def handle(self, *args, **kargs):
        # Delete all Email Verification that are over 30 days old
        now = datetime.datetime.now()
        check_date = now - datetime.timedelta(days=30)
        evs = EmailVerification.objects.filter(last_sent_at__lte=check_date)

Error:
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/vbabiy/projects/git-projects/howsthedotcom/accounts/tests/send_email_verification.py", line 34, in test_mox
    com.handle()
  File "/home/vbabiy/projects/git-projects/howsthedotcom/accounts/management/commands/send_email_verification.py", line 12, in handle
    evs = EmailVerification.objects.filter(last_sent_at__lte=check_date)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/manager.py", line 129, in filter
    return self.get_query_set().filter(*args, **kwargs)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 498, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py", line 516, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1675, in add_q
    can_reuse=used_aliases)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1614, in add_filter
    connector)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py", line 56, in add
    obj, params = obj.process(lookup_type, value)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py", line 269, in process
    params = self.field.get_db_prep_lookup(lookup_type, value)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py", line 507, in get_db_prep_lookup
    return super(DateField, self).get_db_prep_lookup(lookup_type, value)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py", line 210, in get_db_prep_lookup
    return [self.get_db_prep_value(value)]
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py", line 569, in get_db_prep_value
    return connection.ops.value_to_db_datetime(self.to_python(value))
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py", line 533, in to_python
    if isinstance(value, datetime.datetime):
  File "/var/lib/python-support/python2.6/mox.py", line 414, in __getattr__
    raise UnknownMethodCallError(name)
UnknownMethodCallError: Method called is not a member of the object: __bases__


Thanks
Vitaly Babiy

David Glasser

unread,
Jun 21, 2009, 7:17:45 PM6/21/09
to mox-d...@googlegroups.com
It looks like Django accesses datetime.datetime in a way that would
require using further mocking.

I'd recommend going my other route where you don't mock out
datetime.datetime itself (which is pretty global), but rather change
the use of datetime.datetime.now() in Command to something like
self.getCurrentDateTime() which you can that mock out. (Or you can
make it a function in a module rather than a method, whatever.) This
leaves datetime.datetime alone so that django's internal use of it
doesn't break.

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/

Vitaly Babiy

unread,
Jun 24, 2009, 10:40:21 AM6/24/09
to mox-d...@googlegroups.com
Yeah, this is what I have done.

It would nice if the exception would show what method is being called that needs to mocked.

thanks
Vitaly Babiy

David Glasser

unread,
Jun 24, 2009, 10:58:57 AM6/24/09
to mox-d...@googlegroups.com
It does:

> UnknownMethodCallError: Method called is not a member of the object:
> __bases__

"__bases__", which I guess is indirectly called by isinstance.

--dave
--
gla...@davidglasser.net | langtonlabs.org | flickr.com/photos/glasser/
Reply all
Reply to author
Forward
0 new messages