How to use mocking to check next_day_of_week function

I track events that repeat on a specific day of the week (for example, on the first Sunday of the month, on the third Friday of the month). I have a DayOfWeek model that stores the day of the week event. It contains the next_day_of_week method to return a date object set to the next occurrence of the day of the week that this instance of the event is installed (this helps to find out when the next event will occur).

For example, on Sunday, 7/3/2011:

  • For an object with DayOfWeek set on Sunday, next_day_of_week will return on 7/3/2011.
  • For DayOfWeek, installed on Monday, it will be back on 7/4/2011.
  • For DayOfWeek, set on Saturday, it will return on 7/9/2011.

And so on. I write unit tests (my first time, did I mention that I'm pretty new to this?) And trying to wrap my head around how to test this method. I know that I need to mock something, but I'm not quite sure what. This question seems to depend on what I'm asking: Python: trying to mock datetime.date.today (), but not working

So I'm trying to make fun of datetime.date in test.py:

class FakeDate(date): "A fake replacement for date that can be mocked for testing." def __new__(cls, *args, **kwargs): return date.__new__(date, *args, **kwargs) 

And I create my test case by fixing in the mock class and installing today until 7/3/2011:

 class TestDayOfWeek(TestCase): """Test the day of the week functions.""" @mock.patch('datetime.date', FakeDate) def test_valid_my_next_day_of_week_sameday(self): from datetime import date FakeDate.today = classmethod(lambda cls: date(2011, 7, 3)) # July 3, 2011 is a Sunday new_day_of_week = DayOfWeek.objects.create() new_day_of_week.day = "SU" self.assertEquals(new_day_of_week.my_next_day_of_week(), date(2011, 7, 3)) 

For reference, here is the model class:

 class DayOfWeek(ModelBase): """ Represents a day of the week (on which an event can take place). Because the dates of these events are often designated by terms like 'first Monday' or 'third Friday', this field is useful in determining on which dates individual readings take place. """ # The pk in the db is 1-indexed (Monday=1, Tuesday=2, etc), but python days # of the week are 0-indexed if you use .weekday(), so we are using .isoweekday() # instead. This list is used in my_next_day_of_week. days =[ 'No day', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ] DAYS_OF_WEEK_CHOICES = ( ('MO', days[1]), ('TU', days[2]), ('WE', days[3]), ('TH', days[4]), ('FR', days[5]), ('SA', days[6]), ('SU', days[7]), ) day = models.CharField(max_length=2, choices=DAYS_OF_WEEK_CHOICES) def __unicode__(self): for daypair in self.DAYS_OF_WEEK_CHOICES: if self.day in daypair: return daypair[1] # This shouldn't happen raise InvalidDayOfWeekError # my_next_day_of_week returns a datetime equal to the start (midnight+min) of the next day that is this instance day of the week. # It doesn't know what time the event is, so if today is the day of the week the event falls on, # it simply returns today. def my_next_day_of_week(self): """ Returns a datetime equal to the start of the next day that is this instance day of the week. """ today_day = date.today().isoweekday() # Find the number of the current day of the week reading_day = self.days.index(self.__unicode__()) # Find the number of the instance day of the week # There is probably a more pythonic way to do this next part next_day = date.today() # start with next day = today while next_day.isoweekday() != reading_day: next_day = next_day + timedelta(1) return next_day 

So when I run the django test runner, the test fails because my DayOfWeek instance does not seem to use mock datetime.date and instead sees today the actual day. From my reading, I understand that the layout exists only in the testing method, and not before or after. But does this also mean that it does not exist for any objects / methods that are created or called from the test method? Then what is its use? I do not think that the problem, but rather that I am doing something wrong when correcting. Maybe a problem with namespaces? I read this: http://www.voidspace.org.uk/python/mock/patch.html#id2 I will continue to try to fix it and edit it if I can, but until then any pointers will be appreciated!

EDIT: realized that I used datetime.datetime in my model instead of datetime.date. I fixed this and edited the above code, but the main problem of an elegant class that is not used remains.

+7
source share
2 answers

Figured it out. The question was really β€œWhere to fix,” and the answer came from studying the Mock documentation related to above (this page) . The solution was to make fun of the date class in the namespace of the module that contains the models for this application, for example:

  @mock.patch('series.models.date', FakeDate) # mock out the date class in the module that has already imported it via from datetime import date, ie series.models (app_name.module_name) def test_valid_my_next_day_of_week_sameday(self): from datetime import date FakeDate.today = classmethod(lambda cls: date(2011, 7, 3)) # July 3, 2011 is a Sunday new_day_of_week = DayOfWeek.objects.create() new_day_of_week.day = "SU" self.assertEquals(new_day_of_week.my_next_day_of_week(), date(2011, 7, 3)) 

Hope this can help someone else!

+9
source

I think the answer you need is contained in another post . I rewrote according to your needs.

 import datetime class FakeDate(datetime.date): @classmethod def today(cls): return cls(2011, 7, 3) datetime.date = FakeDate class TestDayOfWeek(TestCase): """Test the day of the week functions.""" def test_valid_my_next_day_of_week_sameday(self): new_day_of_week = DayOfWeek.objects.create() new_day_of_week.day = "SU" self.assertEquals(new_day_of_week.my_next_day_of_week(), date(2011, 7, 3)) 
0
source

All Articles