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

Version 3.2 #23

Merged
merged 4 commits into from
Nov 1, 2020
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using FluentAssertions.AspNetCore.Mvc.Sample.Controllers;
using Microsoft.AspNetCore.Mvc;
using System;
using Xunit;

namespace FluentAssertions.AspNetCore.Mvc.Sample.Tests
Expand All @@ -25,8 +24,10 @@ public void GetActionResultOfT_OnFalse_Returns_Data()

var result = controller.GetActionResultOfT(model, returnError);

result.Should().BeConvertibleTo<ObjectResult>()
.And.Value.Should().BeSameAs(model);
result.Should().BeObjectResult()
.WithValue(model) // Equals check
.WithValueEquivalentTo(model) // Equivalency check
.WithValueMatch<Models.ProductViewModel>(m => m.Id == 1); // match check.
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public FileStreamResultAssertions BeFileStreamResult(string reason = "", params
}

/// <summary>
/// Asserts that the subject is an <see cref="FileStreamResult"/>.
/// Asserts that the subject is an <see cref="PhysicalFileResult"/>.
/// </summary>
/// <param name="reason">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ public AndWhichConstraint<ActionResultAssertions<TValue>, TActionResult> BeConve

return new AndWhichConstraint<ActionResultAssertions<TValue>, TActionResult>(this, (TActionResult)convertResult);
}

/// <summary>
/// Asserts that the <see cref="ActionResult{TValue}.Result"/> is type of <see cref="ObjectResult"/>.
/// </summary>
/// <param name="reason">
/// 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="reasonArgs">
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
/// </param>
[CustomAssertion]
public ObjectResultAssertions BeObjectResult(string reason = "", params object[] reasonArgs)
{
var result = BeConvertibleTo<ObjectResult>(reason, reasonArgs).Which;

return new ObjectResultAssertions(result);
}

#endregion Public Methods
}
#endregion Public Methods
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Copyright>Copyright 2018</Copyright>
<AssemblyTitle>Fluent Assertions extensions for ASP.NET Core MVC</AssemblyTitle>
<Title>Fluent Assertions for ASP.NET Core MVC</Title>
<VersionPrefix>3.1.0</VersionPrefix>
<VersionPrefix>3.2.0</VersionPrefix>
<Authors>Casey Burns;Kevin Kuszyk</Authors>
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
<AssemblyName>FluentAssertions.AspNetCore.Mvc</AssemblyName>
Expand Down
102 changes: 99 additions & 3 deletions src/FluentAssertions.AspNetCore.Mvc/ObjectResultAssertionsBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using FluentAssertions.Execution;
using FluentAssertions.Common;
using FluentAssertions.Equivalency;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
Expand Down Expand Up @@ -157,14 +159,108 @@ public TObjectResultAssertion WithDeclaredType(Type expectedDeclaredType, string
var actual = ObjectResultSubject.DeclaredType;

Execute.Assertion
.BecauseOf(reason, reasonArgs)
.ForCondition(expectedDeclaredType == actual)
.WithDefaultIdentifier(Identifier + ".DeclaredType")
.BecauseOf(reason, reasonArgs)
.FailWith(FailureMessages.CommonTypeFailMessage, expectedDeclaredType, actual);

return (TObjectResultAssertion)this;
}

/// <summary>
/// Asserts that the <see cref="ObjectResult.Value"/> is the expected value.
/// </summary>
/// <param name="expectedValue">The expected value.</param>
/// <param name="reason">
/// 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="reasonArgs">
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
/// </param>
public TObjectResultAssertion WithValue(object expectedValue, string reason = "", params object[] reasonArgs)
{
object actualValue = ObjectResultSubject.Value;

Execute.Assertion
.BecauseOf(reason, reasonArgs)
.ForCondition(actualValue.IsSameOrEqualTo(expectedValue))
.WithDefaultIdentifier(Identifier + ".Value")
.FailWith(FailureMessages.CommonFailMessage, expectedValue, actualValue);

return (TObjectResultAssertion)this;
}

/// <summary>
/// Asserts that the <see cref="ObjectResult.Value"/> is equivalent to another object.
/// </summary>
/// <param name="expectation">The expected value.</param>
/// <param name="reason">
/// 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="reasonArgs">
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
/// </param>
public TObjectResultAssertion WithValueEquivalentTo<TExpectation>(TExpectation expectation,
string reason = "", params object[] reasonArgs)
{
return WithValueEquivalentTo(expectation, config => config, reason, reasonArgs);
}

/// <summary>
/// Asserts that the <see cref="ObjectResult.Value"/> is equivalent to another object.
/// </summary>
/// <param name="expectation">The expected status code.</param>
/// <param name="config">
/// A reference to the <see cref="EquivalencyAssertionOptions{TSubject}"/> configuration object that can be used
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
/// <see cref="EquivalencyAssertionOptions{TSubject}"/> class. The global defaults are determined by the
/// <see cref="AssertionOptions"/> class.
/// </param>
/// <param name="reason">
/// 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="reasonArgs">
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
/// </param>
public TObjectResultAssertion WithValueEquivalentTo<TExpectation>(TExpectation expectation,
Func<EquivalencyAssertionOptions<TExpectation>, EquivalencyAssertionOptions<TExpectation>> config, string reason = "", params object[] reasonArgs)
{
object actualValue = ObjectResultSubject.Value;

actualValue.Should().BeEquivalentTo(expectation, config, reason, reasonArgs);

return (TObjectResultAssertion)this;
}


/// <summary>
/// Asserts that the <see cref="ObjectResult.Value"/> statisfies the <paramref name="predicate"/>.
/// </summary>
/// <param name="predicate">
/// The predicate which must be satisfied by the <see cref="ObjectResult.Value"/>.
/// </param>
/// <param name="reason">
/// 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="reasonArgs">
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
/// </param>
public TObjectResultAssertion WithValueMatch<TExpectation>(Expression<Func<TExpectation, bool>> predicate,
string reason = "", params object[] reasonArgs)
{
object actualValue = ValueAs<TExpectation>();

using(var scope = new AssertionScope(Identifier + ".Value"))
{
actualValue.Should().Match(predicate, reason, reasonArgs);
}

return (TObjectResultAssertion)this;
}

/// <summary>
/// Asserts that the <see cref="ObjectResult.StatusCode"/> is the expected status code.
Expand All @@ -182,9 +278,9 @@ public TObjectResultAssertion WithStatusCode(int? expectedStatusCode, string rea
var actual = ObjectResultSubject.StatusCode;

Execute.Assertion
.BecauseOf(reason, reasonArgs)
.ForCondition(expectedStatusCode == actual)
.WithDefaultIdentifier(Identifier + ".StatusCode")
.BecauseOf(reason, reasonArgs)
.FailWith(FailureMessages.CommonFailMessage, expectedStatusCode, actual);

return (TObjectResultAssertion)this;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using FluentAssertions.Mvc.Tests.Helpers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using System;
using Xunit;

Expand Down Expand Up @@ -72,6 +71,28 @@ public void BeConvertibleTo_ShouldBeTheConvertedObject()

actual.Should().BeSameAs(expectation);
}

[Fact]
public void BeObjectResult_GivenActionResultWithObjectResult_ShouldPass()
{
var result = new ActionResult<object>(new object());

result.Should().BeObjectResult(Reason, ReasonArgs);
}

[Fact]
public void BeObjectResult_GivenActionResultWithNotObjectResult_ShouldFail()
{
var result = new ActionResult<object>(new BadRequestObjectResult(new object()));
var failureMessage = FailureMessageHelper.ExpectedContextToBeConvertible(
"result", typeof(ObjectResult).FullName, typeof(BadRequestObjectResult).FullName);

Action action = () => result.Should().BeObjectResult(Reason, ReasonArgs);

action.Should().Throw<Exception>()
.WithMessage(failureMessage);
}

#endregion Public Methods
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ namespace FluentAssertions.AspNetCore.Mvc.Tests
public class ObjectResultAssertions_Tests
{
private const string TestValue = "testValue";
private const string WrongValue = "wrongValue";

private readonly object TestObject = new { Value = "testValue" };
private readonly object GoodObject = new { Value = "testValue" };
private readonly object WrongObject = new { Value = "wrongValue" };
public const string Reason = FailureMessageHelper.Reason;
public readonly static object[] ReasonArgs = FailureMessageHelper.ReasonArgs;

Expand Down Expand Up @@ -219,5 +224,81 @@ public void WithStatusCode_GivenUnexpected_ShouldFail()
a.Should().Throw<Exception>()
.WithMessage(failureMessage);
}

[Fact]
public void WithValue_GivenExpected_ShouldPass()
{
var result = new ObjectResult(TestValue);

result.Should().BeObjectResult()
.WithValue(TestValue);
}

[Fact]
public void WithValue_GivenUnexpected_ShouldFail()
{
var result = new ObjectResult(WrongValue);
string failureMessage = FailureMessageHelper.ExpectedContextToBeXButY(
"ObjectResult.Value",
TestValue,
WrongValue);

Action a = () => result.Should().BeObjectResult().WithValue(TestValue, Reason, ReasonArgs);

a.Should().Throw<Exception>()
.WithMessage(failureMessage);
}

[Fact]
public void WithValueEquivalentTo_GivenExpected_ShouldPass()
{
var result = new ObjectResult(TestObject);

result.Should().BeObjectResult()
.WithValueEquivalentTo(GoodObject);
}

[Fact]
public void WithValueEquivalentTo_GivenUnexpected_ShouldFail()
{
var result = new ObjectResult(WrongObject);
string failureMessage = @"Expected member Value to be
""testValue"" with a length of 9 because it is 10, but
""wrongValue"" has a length of 10.

With configuration:
- Use declared types and members
- Compare enums by value
- Match member by name (or throw)
- Without automatic conversion.
- Be strict about the order of items in byte arrays";

Action a = () => result.Should().BeObjectResult().WithValueEquivalentTo(GoodObject, Reason, ReasonArgs);

a.Should().Throw<Exception>()
.WithMessage(failureMessage);
}

[Fact]
public void WithValueMatch_GivenExpected_ShouldPass()
{
var result = new ObjectResult(TestValue);

result.Should().BeObjectResult()
.WithValueMatch<string>(value => value == TestValue);
}

[Fact]
public void WithValueMatch_GivenUnexpected_ShouldFail()
{
var result = new ObjectResult(WrongValue);
string failureMessage = "Expected ObjectResult.Value to match (value == \"testValue\") because it is 10, but found \"wrongValue\".";

Action a = () => result.Should().BeObjectResult().WithValueMatch<string>(value => value == TestValue, Reason, ReasonArgs);

a.Should().Throw<Exception>()
.WithMessage(failureMessage);
}

}
}