-
Notifications
You must be signed in to change notification settings - Fork 337
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#if NET6_0_OR_GREATER | ||
|
||
using System; | ||
using System.Reflection; | ||
using AutoFixture.Kernel; | ||
|
||
namespace AutoFixture; | ||
|
||
/// <summary> | ||
/// Creates random <see cref="TimeOnly"/> specimens. | ||
/// </summary> | ||
/// <remarks> | ||
/// The generated <see cref="TimeOnly"/> values will be within | ||
/// a range of ± six hours from noon, | ||
/// unless a different range has been specified in the constructor. | ||
/// </remarks> | ||
public class RandomTimeOnlySequenceGenerator : ISpecimenBuilder | ||
{ | ||
private static readonly TimeOnly Default = new(12, 0); | ||
private readonly RandomNumericSequenceGenerator randomizer; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RandomTimeOnlySequenceGenerator"/> class. | ||
/// </summary> | ||
public RandomTimeOnlySequenceGenerator() | ||
: this(Default.AddHours(-6), Default.AddHours(6)) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RandomTimeOnlySequenceGenerator"/> class | ||
/// for a specific range of time. | ||
/// </summary> | ||
/// <param name="minTime">The lower bound of the time range.</param> | ||
/// <param name="maxTime">The upper bound of the time range.</param> | ||
/// <exception cref="ArgumentException"> | ||
/// <paramref name="minTime"/> is greater than <paramref name="maxTime"/>. | ||
/// </exception> | ||
public RandomTimeOnlySequenceGenerator(TimeOnly minTime, TimeOnly maxTime) | ||
{ | ||
if (minTime >= maxTime) | ||
{ | ||
throw new ArgumentException("The 'minTime' argument must be less than the 'maxTime'."); | ||
} | ||
|
||
this.randomizer = new RandomNumericSequenceGenerator(minTime.Ticks, maxTime.Ticks); | ||
} | ||
|
||
/// <summary> | ||
/// Creates a new <see cref="TimeOnly"/> specimen based on a request. | ||
/// </summary> | ||
/// <param name="request">The request that describes what to create.</param> | ||
/// <param name="context">Not used.</param> | ||
/// <returns> | ||
/// A new <see cref="TimeOnly"/> specimen, if <paramref name="request"/> is a request for a | ||
/// <see cref="TimeOnly"/> value; otherwise, a <see cref="NoSpecimen"/> instance. | ||
/// </returns> | ||
public object Create(object request, ISpecimenContext context) | ||
{ | ||
if (context is null) throw new ArgumentNullException(nameof(context)); | ||
|
||
if (!typeof(TimeOnly).GetTypeInfo().IsAssignableFrom(request as Type)) | ||
{ | ||
return new NoSpecimen(); | ||
} | ||
|
||
var ticks = (long)this.randomizer.Create(typeof(long), context); | ||
return new TimeOnly(ticks); | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 168 additions & 0 deletions
168
Src/AutoFixtureUnitTest/RandomTimeOnlySequenceGeneratorTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#if NET6_0_OR_GREATER | ||
|
||
using System; | ||
using System.Linq; | ||
using AutoFixture; | ||
using AutoFixture.Kernel; | ||
using AutoFixtureUnitTest.Kernel; | ||
using Xunit; | ||
|
||
namespace AutoFixtureUnitTest; | ||
|
||
public class RandomTimeOnlySequenceGeneratorTest | ||
{ | ||
[Fact] | ||
public void SutIsSpecimenBuilder() | ||
{ | ||
// Arrange & Act | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
|
||
// Assert | ||
Assert.IsAssignableFrom<ISpecimenBuilder>(sut); | ||
} | ||
|
||
[Fact] | ||
public void InitializeWithInvertedRangeThrowsArgumentException() | ||
{ | ||
// Arrange | ||
var minimum = new TimeOnly(12, 03, 21); | ||
var maximum = minimum.AddHours(3); | ||
|
||
// Act & assert | ||
Assert.Throws<ArgumentException>( | ||
() => new RandomTimeOnlySequenceGenerator(maximum, minimum)); | ||
} | ||
|
||
[Fact] | ||
public void InitializeWithEmptyRangeThrowsArgumentException() | ||
{ | ||
// Arrange | ||
var time = new TimeOnly(14, 13, 09); | ||
|
||
// Act & assert | ||
Assert.Throws<ArgumentException>( | ||
() => new RandomTimeOnlySequenceGenerator(time, time)); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithNullRequestReturnsNoSpecimen() | ||
{ | ||
// Arrange | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
|
||
// Act | ||
var result = sut.Create(null, dummyContainer); | ||
|
||
// Assert | ||
Assert.Equal(new NoSpecimen(), result); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithNullContextThrowsArgumentNullException() | ||
{ | ||
// Arrange | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
|
||
// Act & assert | ||
Assert.Throws<ArgumentNullException>( | ||
() => sut.Create(typeof(TimeOnly), null)); | ||
} | ||
|
||
[Theory] | ||
[InlineData("")] | ||
[InlineData(default(int))] | ||
[InlineData(default(bool))] | ||
public void CreateWithNonTypeRequestReturnsNoSpecimen(object request) | ||
{ | ||
// Arrange | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
|
||
// Act | ||
var result = sut.Create(request, dummyContainer); | ||
|
||
// Assert | ||
Assert.Equal(new NoSpecimen(), result); | ||
} | ||
|
||
[Theory] | ||
[InlineData(typeof(string))] | ||
[InlineData(typeof(object))] | ||
[InlineData(typeof(int))] | ||
[InlineData(typeof(bool))] | ||
public void CreateWithNonTimeOnlyTypeRequestReturnsNoSpecimen(Type request) | ||
{ | ||
// Arrange | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
|
||
// Act | ||
var result = sut.Create(request, dummyContainer); | ||
|
||
// Assert | ||
Assert.Equal(new NoSpecimen(), result); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithTimeOnlyRequestReturnsTimeOnlyValue() | ||
{ | ||
// Arrange | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
|
||
// Act | ||
var result = sut.Create(typeof(TimeOnly), dummyContainer); | ||
|
||
// Assert | ||
Assert.IsAssignableFrom<TimeOnly>(result); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithTimeOnlyRequestReturnsADateWithinARangeOfPlusMinusTwoYearsFromNoon() | ||
{ | ||
// Arrange | ||
var current = new TimeOnly(12, 00); | ||
var twoHoursAgo = current.AddHours(-6); | ||
var twoHoursForward = current.AddHours(6); | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
// Act | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
var result = (TimeOnly)sut.Create(typeof(TimeOnly), dummyContainer); | ||
// Assert | ||
Assert.InRange(result, twoHoursAgo, twoHoursForward); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithMultipleRequestsReturnsDifferentTimes() | ||
{ | ||
// Arrange | ||
const int requestCount = 10; | ||
var times = Enumerable.Range(1, requestCount); | ||
var sut = new RandomTimeOnlySequenceGenerator(); | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
|
||
// Act | ||
var results = times | ||
.Select(t => sut.Create(typeof(TimeOnly), dummyContainer)) | ||
.Cast<TimeOnly>(); | ||
|
||
// Assert | ||
Assert.Equal(requestCount, results.Distinct().Count()); | ||
} | ||
|
||
[Fact] | ||
public void CreateWithTimeOnlyRequestAndTimeRangeReturnsValueWithinThatRange() | ||
{ | ||
// Arrange | ||
var minimum = new TimeOnly(13, 00); | ||
var maximum = minimum.AddHours(3); | ||
var sut = new RandomTimeOnlySequenceGenerator(minimum, maximum); | ||
// Act | ||
var dummyContainer = new DelegatingSpecimenContext(); | ||
var result = (TimeOnly)sut.Create(typeof(TimeOnly), dummyContainer); | ||
// Assert | ||
Assert.InRange(result, minimum, maximum); | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters