Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BeDefined and NotBeDefined to EnumAssertions #1888

Merged
merged 4 commits into from Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 52 additions & 0 deletions Src/FluentAssertions/Primitives/EnumAssertions.cs
Expand Up @@ -129,6 +129,58 @@ public AndConstraint<TAssertions> Be(TEnum? expected, string because = "", param
return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that the current value of <typeparamref name="TEnum"/> is defined inside the enum.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.WithExpectation("Expected {context:the enum} to be defined in {0}{reason}, ", typeof(TEnum))
IT-VBFK marked this conversation as resolved.
Show resolved Hide resolved
.ForCondition(Subject is not null)
.FailWith("but found <null>.")
.Then
.ForCondition(Enum.IsDefined(typeof(TEnum), Subject))
.FailWith("but it is not.")
.Then
.ClearExpectation();

return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that the current value of <typeparamref name="TEnum"/> is not defined inside the enum.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.WithExpectation("Did not expect {context:the enum} to be defined in {0}{reason}, ", typeof(TEnum))
.ForCondition(Subject is not null)
.FailWith("but found <null>.")
.Then
.ForCondition(!Enum.IsDefined(typeof(TEnum), Subject))
.FailWith("but it is.")
.Then
.ClearExpectation();

return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that the current <typeparamref name="TEnum"/> is exactly equal to the <paramref name="expected"/> value.
/// </summary>
Expand Down
Expand Up @@ -1887,6 +1887,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1899,6 +1900,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
Expand Up @@ -1944,6 +1944,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1956,6 +1957,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
Expand Up @@ -1887,6 +1887,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1899,6 +1900,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
Expand Up @@ -1887,6 +1887,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1899,6 +1900,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
Expand Up @@ -1839,6 +1839,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1851,6 +1852,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
Expand Up @@ -1887,6 +1887,7 @@ namespace FluentAssertions.Primitives
public TEnum? Subject { get; }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> Be(TEnum? expected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(params TEnum[] validValues) { }
public FluentAssertions.AndConstraint<TAssertions> BeOneOf(System.Collections.Generic.IEnumerable<TEnum> validValues, string because = "", params object[] becauseArgs) { }
public override bool Equals(object obj) { }
Expand All @@ -1899,6 +1900,7 @@ namespace FluentAssertions.Primitives
public FluentAssertions.AndConstraint<TAssertions> Match(System.Linq.Expressions.Expression<System.Func<TEnum?, bool>> predicate, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBe(TEnum? unexpected, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotBeDefined(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveFlag(TEnum unexpectedFlag, string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotHaveSameNameAs<T>(T unexpected, string because = "", params object[] becauseArgs)
where T : struct, System.Enum { }
Expand Down
79 changes: 79 additions & 0 deletions Tests/FluentAssertions.Specs/Primitives/EnumAssertionSpecs.cs
Expand Up @@ -791,5 +791,84 @@ public void An_enum_cannot_be_part_of_a_null_list()
}

#endregion

#region Be defined / Not be defined

[Fact]
public void A_valid_entry_of_an_enum_is_defined()
{
// Arrange
var dayOfWeek = (DayOfWeek)1;

// Act / Assert
dayOfWeek.Should().BeDefined();
}

[Fact]
public void If_a_value_casted_to_an_enum_type_and_it_does_not_exist_in_the_enum_it_throws()
{
// Arrange
var dayOfWeek = (DayOfWeek)999;

// Act
Action act = () => dayOfWeek.Should().BeDefined("we want to test the failure {0}", "message");

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Expected *to be defined in*failure message*, but it is not*");
}

[Fact]
public void A_null_entry_of_an_enum_throws()
{
// Arrange
MyEnum? subject = null;

// Act
Action act = () => subject.Should().BeDefined();

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Expected *to be defined in*, but found <null>.");
}

[Fact]
public void An_invalid_entry_of_an_enum_is_not_defined_passes()
{
// Arrange
var dayOfWeek = (DayOfWeek)999;

// Act / Assert
dayOfWeek.Should().NotBeDefined();
}

[Fact]
public void A_valid_entry_of_an_enum_is_not_defined_fails()
{
// Arrange
var dayOfWeek = (DayOfWeek)1;

// Act
Action act = () => dayOfWeek.Should().NotBeDefined();

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Did not expect*to be defined in*, but it is.");
}

[Fact]
public void A_null_value_of_an_enum_is_not_defined_and_throws()
{
// Arrange
MyEnum? subject = null;

// Act
Action act = () => subject.Should().NotBeDefined();

// Assert
act.Should().Throw<XunitException>()
.WithMessage("Did not expect *to be defined in*, but found <null>.");
}
#endregion
}
}
8 changes: 8 additions & 0 deletions docs/_pages/enums.md
Expand Up @@ -42,3 +42,11 @@ Lastly, if you want to verify than an enum has a specific integral value, you ca
MyEnum.One.Should().HaveValue(1);
MyEnum.One.Should().NotHaveValue(2);
```

```csharp
var myEnum = (MyEnum)1;
myEnum.Should().BeDefined();

myEnum = (MyEnum)99;
myEnum.Should().NotBeDefined();
```
5 changes: 5 additions & 0 deletions docs/_pages/releases.md
Expand Up @@ -9,6 +9,11 @@ sidebar:

## Unreleased

### What's new
* Add `BeDefined` and `NotBeDefined` to assert on existence of an enum value - [#1888](https://github.com/fluentassertions/fluentassertions/pull/1888)

## 6.6.0

### What's New
* Annotated `[Not]MatchRegex(string)` with `[StringSyntax("Regex")]` which IDEs can use to colorize the regular expression argument - [#1816](https://github.com/fluentassertions/fluentassertions/pull/1816)
* Added support for .NET6 `DateOnly` struct - [#1844](https://github.com/fluentassertions/fluentassertions/pull/1844)
Expand Down