Skip to content

Commit

Permalink
Merge pull request #23 from faddiv/master
Browse files Browse the repository at this point in the history
Version 3.2
  • Loading branch information
faddiv committed Nov 1, 2020
2 parents 4637031 + 3f7d785 commit 0357e47
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 10 deletions.
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 ActionResultAssertions(ActionResult<TValue> subject)

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);
}

}
}

0 comments on commit 0357e47

Please sign in to comment.