3 ms·
Great idea! But how does one make a virtual implementation of time/scheduler?
by porker 10y ago
Great idea! But how does one make a virtual implementation of time/scheduler?
- edejong 10y agoEvery function which returns the current time, should be dependency injected with a 'currentTimeService'. This service, during tests, is injected with your mock implementation, and during production with a simple call to 'new DateTime()' or sth like that.
- hermannj314 10y agoI 100% agree. I've pitched this before (during a code review for something) and was laughed at by the team under some guise of YAGNI / developer gold plating. They honestly thought I was joking. Once I explained the issues mentioned in the article, they still thought it was a waste of time. It takes just a few seconds to implement and makes the code so much easier to test / maintain.
- edejong 10y agoTell them we're currently replaying test scenario's involving thousands of truck routes per day (and around a thousand trucks). This allows us to easily recreate bugs and see the effects of fixes, new algorithms, etc. etc. Couldn't do it with some DI on the whole system and simulated time.
- rubber_duck 10y agoWhat edejong said basically, Rx library uses this concept really well - you can see for example in .NET implementation [1] how the scheduler interface looks like. They basically abstract system timer and scheduling tasks, then you can implement you own virtual time implementation where current time is just a property that you can manually set, and when you change it you go trough the list of scheduled tasks and see if you need to execute any before the new current time. [1] https://msdn.microsoft.com/en-us/library/system.concurrency.ischeduler_members(v=vs.92).aspx https://msdn.microsoft.com/en-us/library/system.concurrency....
- PJDK 10y agoOur solution in c# with dependency injection looks like this. Any class that needs to know the time has the following object injected in. public interface IDateTime { DateTime UtcNow { get; } DateTime Today { get; } } StructureMap is configured to pass in the following concrete implementation. public class DefaultDateTime : IDateTime { public DateTime UtcNow { get { return DateTime.UtcNow; } } public DateTime Today { get { return DateTime.Today; } } } Obviously you can expand this to include local time, we haven't in order to prevent accidental use of Now when you mean UtcNow. All of our tests inherit from a base test that does various set up stuff (clear down the db in integration tests for example). One of the things it does is swap out DefaultDateTime with this... public class TestDateTime : IDateTime { private DateTime _testDateTime; public TestDateTime(DateTime testDateTime) { _testDateTime = testDateTime; } public void ChangeTimeTo(DateTime testDateTime) { _testDateTime = testDateTime; } public DateTime UtcNow { get { return _testDateTime.ToUniversalTime(); } public DateTime Today { get { return _testDateTime.Date; } } } Where _testDateTime is set to be sometime in August (always a good idea if you're developing in the UK!). This has the added advantage of making test runs deterministic (at least in this respect) even if you're not doing a time related test.
- hirsin 10y agoSorry, what's the connection between August and the UK? Based in the US, but I can't think of a specific month I'd want my tests to run in.
- limeyx 10y agoNot sure for sure but August is probably the least rainy/nasty month in England
- PJDK 10y agoIt's summer time - during the winter the UK runs on UTC, so if you've forgot to do a timezone conversion you don't spot it until the clocks change in spring. Having tests use the time in summer make this easier to spot.