You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Timecop is a small library that helps you test DateTime in a static, thread-safe, ambient context.
3
+
Timecop is a small library that helps to test the code that depends on DateTime by allowing you to freeze and travel in time.
4
4
5
5
Timecop targets .NET Standard 2.0, has no external dependencies, and can be used with .NET Framework 4.5+ and any version of .NET and .NET Core.
6
6
7
7
Timecop has been inspired by the [timecop](https://github.com/travisjeffery/timecop) Ruby gem.
8
8
9
9
## Installation
10
10
11
-
You can install [Timecop](https://www.nuget.org/packages/Timecop/) from NuGet using the .NET CLI:
11
+
You can install [Timecop](https://www.nuget.org/packages/Timecop/) from NuGet using your IDE or the .NET CLI:
12
12
13
13
```
14
14
dotnet add package Timecop
15
15
```
16
16
17
-
## Basic usage
17
+
## Basics and usage
18
18
19
-
Timecop allows you to freeze and travel in time. Just use the `Clock` class instead of `DateTime`to get the current time via `Now` or `UtcNow` properties, and manipulate time with the `Timecop` class in your tests.
19
+
To test with Timecop, your code must get the current time using either:
20
+
- The `IClock` interface injected as a method or a constructor parameter;
21
+
- The static `Clock` class.
22
+
23
+
### Usage with the `IClock` interface
24
+
25
+
Timecop provides the `IClock` interface that exposes the `Now` and `UtcNow` properties.
26
+
27
+
Here's how to use it:
28
+
1. Pass the instance of `IClock` to your code as a method or a constructur parameter and use it to get the current time;
29
+
1. In your tests, configure the `Timecop` instance and pass the `Timecop.Clock` into the code under test;
30
+
1. When running in production, pass the `IClock` implementaton that returns the current time. You can use the [Timecop.Extensions.DependencyInjection](https://github.com/timecop-net/Timecop.Extensions.DependencyInjection) package to register such implementation with the DI container in one line of code.
Timecop provides the static `Clock` class that you can use instead of `DateTime` to get the current local or UTC time. Despite `Clock` being a static class, it is safe to use in tests that run in parallel as it uses [AsyncLocal](https://learn.microsoft.com/en-us/dotnet/api/system.threading.asynclocal-1) under the hood.
62
+
63
+
Here's how to use it:
64
+
1. Replace the calls to `DateTime.Now` and `DateTime.UtcNow` with `Clock.Now` and `Clock.UtcNow`;
65
+
1. In your tests, configure the `Timecop` instance
66
+
67
+
Example:
20
68
21
69
```csharp
22
70
stringGreet()
@@ -45,11 +93,13 @@ Greet(); // Good evening!
45
93
46
94
## Available methods
47
95
96
+
Timecop allows to manipulate time in any imaginable way. Freeze time, travel in time, and resume the flow of time with a simple API.
97
+
48
98
### Freezing and resuming time
49
99
50
-
You can freeze the time so that it stops running for your tests until you call `Resume` or dispose the `Timecop` instance.
100
+
You can freeze the time so that it stops running for your tests until you call `Resume`, `Reset`, or dispose the `Timecop` instance.
51
101
52
-
You freeze time with either an instance `Freeze` or a static `Frozen` method, which both have the same set of overloads. Both methods have the same effect, however the static `Frozen` creates an already frozen `Timecop` instance.
102
+
You freeze time with either an instance `Freeze` or a static `Frozen` method, both having the same set of overloads. Both methods have the same effect, however the static `Frozen` creates an already frozen `Timecop` instance.
// freeze at the specific date or time using PointInTimeBuilder:
166
+
traveledTo=tc.TravelTo(o=>o.On(1990, 12, 2)
167
+
.At(14, 13, 51)
168
+
.InLocalZone());
169
+
```
170
+
171
+
### Using PointInTimeBuilder
172
+
173
+
`Freeze`, `Frozen`, and `TravelTo` methods each accept a lambda that allows to configure the time with the `PointInTimeBuilder` class.
174
+
175
+
Use `PointInTimeBuilder` to specify different components of date and time. When using `At` and `On` methods, always specify whether the time is local or UTC using `InLocalZone` or `InUtc`.
176
+
177
+
178
+
```csharp
179
+
// When only the date matters:
180
+
builder.On(1990, 12, 2).InLocalZone(); // will use the specified date and current time
181
+
182
+
// When only the time matters:
183
+
builder.At(14, 13, 51).InLocalZone(); // will use the specified time and current date
184
+
185
+
// When neither the date nor time matter, but the date must be in the future or in the past:
186
+
builder.InTheFuture();
187
+
188
+
builder.InThePast();
189
+
```
190
+
103
191
## License
104
192
105
193
Timecop was created by [Dmytro Khmara](https://dmytrokhmara.com) and is licensed under the [MIT license](LICENSE.txt).
publicPointInTimeBuilderNeitherLocalNorUtcException():base($"Call either {nameof(PointInTimeBuilder.LocalTime)}() or {nameof(PointInTimeBuilder.UtcTime)}() when configuring the point in time.")
7
+
publicPointInTimeBuilderNeitherLocalNorUtcException():base($"Call either {nameof(PointInTimeBuilder.InLocalZone)}() or {nameof(PointInTimeBuilder.InUtc)}() when configuring the point in time.")
@@ -34,7 +34,7 @@ public void Build_OnWasCalled_ButNeitherLocalNorUtcWasCalled_ShouldThrow()
34
34
35
35
varbuild=()=>_builder.Build(out_);
36
36
37
-
build.Should().Throw<PointInTimeBuilderNeitherLocalNorUtcException>().WithMessage("Call either LocalTime() or UtcTime() when configuring the point in time.");
37
+
build.Should().Throw<PointInTimeBuilderNeitherLocalNorUtcException>().WithMessage("Call either InLocalZone() or InUtc() when configuring the point in time.");
38
38
}
39
39
40
40
[Fact]
@@ -44,7 +44,7 @@ public void Build_AtWasCalled_ButNeitherLocalNorUtcWasCalled_ShouldThrow()
44
44
45
45
varbuild=()=>_builder.Build(out_);
46
46
47
-
build.Should().Throw<PointInTimeBuilderNeitherLocalNorUtcException>().WithMessage("Call either LocalTime() or UtcTime() when configuring the point in time.");
47
+
build.Should().Throw<PointInTimeBuilderNeitherLocalNorUtcException>().WithMessage("Call either InLocalZone() or InUtc() when configuring the point in time.");
48
48
}
49
49
50
50
[Fact]
@@ -59,7 +59,7 @@ public void InTheFuture_ShouldReturnPointOfTimeInTheFuture()
0 commit comments