-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add An<T> for argument constraints and specs
- Loading branch information
1 parent
6783267
commit 01adfb2
Showing
2 changed files
with
197 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
namespace FakeItEasy | ||
{ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Diagnostics.CodeAnalysis; | ||
|
||
/// <summary> | ||
/// Provides an API entry point for constraining arguments of fake object calls. | ||
/// </summary> | ||
/// <typeparam name="T">The type of argument to validate.</typeparam> | ||
/// <remarks>This is a synonym of <see cref="A{T}"/>, to enable proper grammar when the type of T starts with a vowel.</remarks> | ||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = nameof(A), Justification = "It is spelled correctly.")] | ||
public static class An<T> | ||
{ | ||
/// <summary> | ||
/// Gets an argument constraint object that will be used to constrain a method call argument. | ||
/// </summary> | ||
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This is a special case where the type parameter acts as an entry point into the fluent api.")] | ||
public static INegatableArgumentConstraintManager<T> That => | ||
ServiceLocator.Resolve<IArgumentConstraintManagerFactory>().Create<T>(); | ||
|
||
/// <summary> | ||
/// Gets a constraint that considers any value of an argument as valid. | ||
/// </summary> | ||
/// <remarks>This is a shortcut for the "Ignored"-property.</remarks> | ||
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This is a special case where the type parameter acts as an entry point into the fluent api.")] | ||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "_", Justification = "Some trickery is allowed, isn't it?")] | ||
[SuppressMessage("Microsoft.Naming", "CA1707:IdentifiersShouldNotContainUnderscores", Justification = "But it's kinda cool right?")] | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
[CLSCompliant(false)] | ||
#pragma warning disable SA1300 // Element must begin with upper-case letter | ||
public static T _ => Ignored; | ||
#pragma warning restore SA1300 // Element must begin with upper-case letter | ||
|
||
/// <summary> | ||
/// Gets a constraint that considers any value of an argument as valid. | ||
/// </summary> | ||
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This is a special case where the type parameter acts as an entry point into the fluent api.")] | ||
public static T Ignored | ||
{ | ||
get { return That.Matches(x => true, x => x.Write(nameof(Ignored))); } | ||
} | ||
} | ||
} |
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,153 @@ | ||
namespace FakeItEasy.Specs | ||
{ | ||
using FluentAssertions; | ||
using Xbehave; | ||
|
||
public static class AnArgumentConstraintSpecs | ||
{ | ||
public interface IFoo | ||
{ | ||
int Bar(int x); | ||
|
||
int Bar(Apple apple); | ||
} | ||
|
||
[Scenario] | ||
public static void AnIntIgnored(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<int>.Ignored argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<int>.Ignored)).Returns(42)); | ||
|
||
"When the configured method is called" | ||
.x(() => result = fake.Bar(123)); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnIntUnderscore(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<int>._ argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<int>._)).Returns(42)); | ||
|
||
"When the configured method is called" | ||
.x(() => result = fake.Bar(123)); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnIntThatWithMatchingArgument(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<int>.That argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<int>.That.Matches(i => i % 2 == 1))).Returns(42)); | ||
|
||
"When the configured method is called with an argument that matches the constraint" | ||
.x(() => result = fake.Bar(123)); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnIntThatWithNonMatchingArgument(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<int>.That argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<int>.That.Matches(i => i % 2 == 1))).Returns(42)); | ||
|
||
"When the configured method is called with an argument that doesn't match the constraint" | ||
.x(() => result = fake.Bar(12)); | ||
|
||
"Then it returns the default value" | ||
.x(() => result.Should().Be(0)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnAppleIgnored(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<Apple>.Ignored argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<Apple>.Ignored)).Returns(42)); | ||
|
||
"When the configured method is called" | ||
.x(() => result = fake.Bar(new Apple("Red"))); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnAppleUnderscore(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<Apple>._ argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<Apple>._)).Returns(42)); | ||
|
||
"When the configured method is called" | ||
.x(() => result = fake.Bar(new Apple("Red"))); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnAppleThatWithMatchingArgument(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<Apple>.That argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<Apple>.That.Matches(a => a.Color == "Red"))).Returns(42)); | ||
|
||
"When the configured method is called with an argument that matches the constraint" | ||
.x(() => result = fake.Bar(new Apple("Red"))); | ||
|
||
"Then it returns the configured value" | ||
.x(() => result.Should().Be(42)); | ||
} | ||
|
||
[Scenario] | ||
public static void AnAppleThatNonWithMatchingArgument(IFoo fake, int result) | ||
{ | ||
"Given a fake" | ||
.x(() => fake = A.Fake<IFoo>()); | ||
|
||
"And a method of the fake configured with the An<Apple>.That argument constraint" | ||
.x(() => A.CallTo(() => fake.Bar(An<Apple>.That.Matches(a => a.Color == "Red"))).Returns(42)); | ||
|
||
"When the configured method is called with an argument that doesn't match the constraint" | ||
.x(() => result = fake.Bar(new Apple("Green"))); | ||
|
||
"Then it returns the default value" | ||
.x(() => result.Should().Be(0)); | ||
} | ||
|
||
public class Apple | ||
{ | ||
public Apple(string color) | ||
{ | ||
this.Color = color; | ||
} | ||
|
||
public string Color { get; } | ||
} | ||
} | ||
} |