class ContextTimeController(Thread): """ Executes a function in a new thread that uses a fake datetime. This allows a test to manipulate time as perceived by the target function. """ """Initializer Behaves exactly like Thread.__init__ except that daemon defaults to True. target -- function to call in the thread parent_context -- inherit dependencies injected into this context """ def __init__(self, target, *args, parent_context, **kwargs): super().__init__(target=target, **kwargs) self.exception_caught = None self.value_returned = None self.fake_datetime = FakeDatetime() self._context = parent_context.spawn() self._target = target """Advance the fake clock by the given interval Raises a RuntimeError if the thread has not been started. Keyword arguments can be anything accepted by datetime.timedelta. """ def advance(self, **kwargs): if not self.ident: raise RuntimeError( "The thread must be started before advancing time") self.fake_datetime.advance(**kwargs) def run(self): self._context.inject(datetime, self.fake_datetime) self._context.attach_to_thread(self) try: self.value_returned = self._target() except Exception as e: self.exception_caught = e
def test_can_advance_by_arbitrary_days(self): fake = FakeDatetime() days = 8 start = fake.now() fake.advance(days=days) expect(fake.now()).to(equal(start + timedelta(days=days)))
def test_can_advance_by_arbitrary_hours(self): fake = FakeDatetime() hours = 23 start = fake.now() fake.advance(hours=hours) expect(fake.now()).to(equal(start + timedelta(hours=hours)))
def test_can_advance_by_arbitrary_minutes(self): fake = FakeDatetime() mins = 4 start = fake.now() fake.advance(minutes=mins) expect(fake.now()).to(equal(start + timedelta(minutes=mins)))
def test_can_advance_by_arbitrary_sec(self): fake = FakeDatetime() sec = 235 start = fake.now() fake.advance(seconds=sec) expect(fake.now()).to(equal(start + timedelta(seconds=sec)))
def test_can_advance_by_arbitrary_ms(self): fake = FakeDatetime() ms = 235 start = fake.now() fake.advance(milliseconds=ms) expect(fake.now()).to(equal(start + timedelta(milliseconds=ms)))