File Coverage

blib/lib/Test/MockDateTime.pm
Criterion Covered Total %
statement 23 23 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod 1 1 100.0
total 32 32 100.0


line stmt bran cond sub pod time code
1             package Test::MockDateTime;
2             {
3             $Test::MockDateTime::VERSION = '0.02';
4             }
5 1     1   263242 use strict;
  1         4  
  1         30  
6 1     1   6 use warnings;
  1         1  
  1         29  
7 1     1   11 use DateTime;
  1         6  
  1         20  
8 1     1   806 use DateTime::Format::DateParse;
  1         17650  
  1         36  
9              
10 1     1   9 use base 'Exporter';
  1         3  
  1         213  
11              
12             our @EXPORT = 'on';
13              
14             =head1 NAME
15              
16             Test::MockDateTime - mock DateTime->now calls during tests
17              
18             =head1 VERSION
19              
20             version 0.02
21              
22             =head1 SYNOPSIS
23              
24             use Test::More;
25             use Test::MockDateTime;
26             use DateTime;
27            
28             on '2013-01-02 03:04:05' => sub {
29             # inside this block all calls to DateTime::now
30             # will report a mocked date.
31            
32             my $now = DateTime->now;
33             is $now->ymd, '2013-01-02', 'occured now';
34             };
35            
36             done_testing;
37              
38             =head1 DESCRIPTION
39              
40             Getting the current time sometimes is not very helpful for testing scenarios.
41             Instead, if you could obtain a known value during the runtime of a testcase
42             will make your results predictable.
43              
44             Why another Date Mocker? I wanted something simple with a very concise usage
45             pattern and a mocked date should only exist and stay constant inside a scope.
46             After leaving the scope the current time should be back. This lead to this
47             tiny module.
48              
49             This simple module allows faking a given date and time for the runtime of
50             a subsequent code block. By default the C keyword is exported into the
51             namespace of the test file. The date to get mocked must be in a format that
52             is recognized by L.
53              
54             on '2013-01-02 03:04:05', sub { ... };
55              
56             is basically the same as
57              
58             {
59             my $now = DateTime::Format::DateParse->parse_datetime(
60             '2013-01-02 03:04:05'
61             );
62            
63             local *DateTime::now = sub { $now->clone };
64            
65             ... everything from code block above
66             }
67              
68             A drawback when relying on this module is that you must know that the module
69             you are testing uses C<<< DateTime->now >>> to obtain the current time.
70             =cut
71              
72             =head1 FUNCTIONS
73              
74             =cut
75              
76             =head2 on $date_and_time, \&code
77              
78             mocks date and time and then executes code
79              
80             =cut
81              
82             sub on {
83 1     1 1 2453 my ($date, $code) = @_;
84              
85 1         12 my $now = DateTime::Format::DateParse->parse_datetime($date);
86              
87 1     1   6 no warnings 'redefine';
  1         2  
  1         111  
88 1     3   1034 local *DateTime::now = sub { $now->clone };
  3         1337  
89              
90 1         4 $code->();
91             }
92              
93             =head1 CAVEATS
94              
95             This module only mocks calls to C<<< DateTime->now >>>. All other ways to
96             obtain a current time are not touched.
97              
98             =head1 SEE ALSO
99              
100             There are some alternatives. Depending on the environment you might consider
101             using one of them instead.
102              
103             =over
104              
105             =item L
106              
107             Very universal, overwrites several subs at compile time and allows to set
108             a fixed or ticking time at any place in your code.
109              
110             =item L
111              
112             Also allows to set a time at various places inside your code.
113              
114             =item L
115              
116             Mocks serveral L functions.
117              
118             =item L
119              
120             Also overwrites several subs at compile time.
121              
122             =back
123              
124             =head1 AUTHOR
125              
126             Wolfgang Kinkeldei, Ewolfgang@kinkeldei.deE
127              
128             =head1 LICENSE
129              
130             This library is free software. You can redistribute it and/or modify
131             it under the same terms as Perl itself.
132              
133             =cut
134              
135             1;