Skip to content

Commit 21a6c3b

Browse files
committed
Add WithValue, WithValueEquivalentTo, WithValueMatch checks to ObjectResult.
1 parent 868a26d commit 21a6c3b

File tree

4 files changed

+182
-6
lines changed

4 files changed

+182
-6
lines changed

samples/FluentAssertions.AspNetCore.Mvc.Sample.Tests/ProductController_Tests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using FluentAssertions.AspNetCore.Mvc.Sample.Controllers;
22
using Microsoft.AspNetCore.Mvc;
3-
using System;
43
using Xunit;
54

65
namespace FluentAssertions.AspNetCore.Mvc.Sample.Tests
@@ -26,7 +25,9 @@ public void GetActionResultOfT_OnFalse_Returns_Data()
2625
var result = controller.GetActionResultOfT(model, returnError);
2726

2827
result.Should().BeObjectResult()
29-
.Value.Should().Be(model);
28+
.WithValue(model) // Equals check
29+
.WithValueEquivalentTo(model) // Equivalency check
30+
.WithValueMatch<Models.ProductViewModel>(m => m.Id == 1); // match check.
3031
}
3132

3233
[Fact]

src/FluentAssertions.AspNetCore.Mvc/ObjectResultAssertionsBase.cs

+98-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using FluentAssertions.Execution;
1+
using FluentAssertions.Common;
2+
using FluentAssertions.Equivalency;
3+
using FluentAssertions.Execution;
24
using FluentAssertions.Primitives;
35
using Microsoft.AspNetCore.Mvc;
46
using Microsoft.AspNetCore.Mvc.Formatters;
@@ -157,14 +159,107 @@ public TObjectResultAssertion WithDeclaredType(Type expectedDeclaredType, string
157159
var actual = ObjectResultSubject.DeclaredType;
158160

159161
Execute.Assertion
162+
.BecauseOf(reason, reasonArgs)
160163
.ForCondition(expectedDeclaredType == actual)
161164
.WithDefaultIdentifier(Identifier + ".DeclaredType")
162-
.BecauseOf(reason, reasonArgs)
163165
.FailWith(FailureMessages.CommonTypeFailMessage, expectedDeclaredType, actual);
164166

165167
return (TObjectResultAssertion)this;
166168
}
167169

170+
/// <summary>
171+
/// Asserts that the <see cref="ObjectResult.Value"/> is the expected value.
172+
/// </summary>
173+
/// <param name="expectedValue">The expected value.</param>
174+
/// <param name="reason">
175+
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
176+
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
177+
/// </param>
178+
/// <param name="reasonArgs">
179+
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
180+
/// </param>
181+
public TObjectResultAssertion WithValue(object expectedValue, string reason = "", params object[] reasonArgs)
182+
{
183+
object actualValue = ObjectResultSubject.Value;
184+
185+
Execute.Assertion
186+
.BecauseOf(reason, reasonArgs)
187+
.ForCondition(actualValue.IsSameOrEqualTo(expectedValue))
188+
.WithDefaultIdentifier(Identifier + ".Value")
189+
.FailWith(FailureMessages.CommonFailMessage, expectedValue, actualValue);
190+
191+
return (TObjectResultAssertion)this;
192+
}
193+
194+
/// <summary>
195+
/// Asserts that the <see cref="ObjectResult.Value"/> is equivalent to another object.
196+
/// </summary>
197+
/// <param name="expectation">The expected value.</param>
198+
/// <param name="reason">
199+
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
200+
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
201+
/// </param>
202+
/// <param name="reasonArgs">
203+
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
204+
/// </param>
205+
public TObjectResultAssertion WithValueEquivalentTo<TExpectation>(TExpectation expectation,
206+
string reason = "", params object[] reasonArgs)
207+
{
208+
return WithValueEquivalentTo(expectation, config => config, reason, reasonArgs);
209+
}
210+
211+
/// <summary>
212+
/// Asserts that the <see cref="ObjectResult.Value"/> is equivalent to another object.
213+
/// </summary>
214+
/// <param name="expectation">The expected status code.</param>
215+
/// <param name="config">
216+
/// A reference to the <see cref="EquivalencyAssertionOptions{TSubject}"/> configuration object that can be used
217+
/// to influence the way the object graphs are compared. You can also provide an alternative instance of the
218+
/// <see cref="EquivalencyAssertionOptions{TSubject}"/> class. The global defaults are determined by the
219+
/// <see cref="AssertionOptions"/> class.
220+
/// </param>
221+
/// <param name="reason">
222+
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
223+
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
224+
/// </param>
225+
/// <param name="reasonArgs">
226+
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
227+
/// </param>
228+
public TObjectResultAssertion WithValueEquivalentTo<TExpectation>(TExpectation expectation,
229+
Func<EquivalencyAssertionOptions<TExpectation>, EquivalencyAssertionOptions<TExpectation>> config, string reason = "", params object[] reasonArgs)
230+
{
231+
object actualValue = ObjectResultSubject.Value;
232+
233+
actualValue.Should().BeEquivalentTo(expectation, config, reason, reasonArgs);
234+
235+
return (TObjectResultAssertion)this;
236+
}
237+
238+
239+
/// <summary>
240+
/// Asserts that the <see cref="ObjectResult.Value"/> statisfies the <paramref name="predicate"/>.
241+
/// </summary>
242+
/// <param name="predicate">
243+
/// The predicate which must be satisfied by the <see cref="ObjectResult.Value"/>.
244+
/// <param name="reason">
245+
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
246+
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
247+
/// </param>
248+
/// <param name="reasonArgs">
249+
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
250+
/// </param>
251+
public TObjectResultAssertion WithValueMatch<TExpectation>(Expression<Func<TExpectation, bool>> predicate,
252+
string reason = "", params object[] reasonArgs)
253+
{
254+
object actualValue = ValueAs<TExpectation>();
255+
256+
using(var scope = new AssertionScope(Identifier + ".Value"))
257+
{
258+
actualValue.Should().Match(predicate, reason, reasonArgs);
259+
}
260+
261+
return (TObjectResultAssertion)this;
262+
}
168263

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

184279
Execute.Assertion
280+
.BecauseOf(reason, reasonArgs)
185281
.ForCondition(expectedStatusCode == actual)
186282
.WithDefaultIdentifier(Identifier + ".StatusCode")
187-
.BecauseOf(reason, reasonArgs)
188283
.FailWith(FailureMessages.CommonFailMessage, expectedStatusCode, actual);
189284

190285
return (TObjectResultAssertion)this;

tests/FluentAssertions.AspNetCore.Mvc.Tests/ActionResultAssertionsOfTValue_Tests.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using FluentAssertions.Mvc.Tests.Helpers;
22
using Microsoft.AspNetCore.Mvc;
3-
using Microsoft.AspNetCore.Mvc.Infrastructure;
43
using System;
54
using Xunit;
65

tests/FluentAssertions.AspNetCore.Mvc.Tests/ObjectResultAssertions_Tests.cs

+81
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ namespace FluentAssertions.AspNetCore.Mvc.Tests
1212
public class ObjectResultAssertions_Tests
1313
{
1414
private const string TestValue = "testValue";
15+
private const string WrongValue = "wrongValue";
16+
17+
private readonly object TestObject = new { Value = "testValue" };
18+
private readonly object GoodObject = new { Value = "testValue" };
19+
private readonly object WrongObject = new { Value = "wrongValue" };
1520
public const string Reason = FailureMessageHelper.Reason;
1621
public readonly static object[] ReasonArgs = FailureMessageHelper.ReasonArgs;
1722

@@ -219,5 +224,81 @@ public void WithStatusCode_GivenUnexpected_ShouldFail()
219224
a.Should().Throw<Exception>()
220225
.WithMessage(failureMessage);
221226
}
227+
228+
[Fact]
229+
public void WithValue_GivenExpected_ShouldPass()
230+
{
231+
var result = new ObjectResult(TestValue);
232+
233+
result.Should().BeObjectResult()
234+
.WithValue(TestValue);
235+
}
236+
237+
[Fact]
238+
public void WithValue_GivenUnexpected_ShouldFail()
239+
{
240+
var result = new ObjectResult(WrongValue);
241+
string failureMessage = FailureMessageHelper.ExpectedContextToBeXButY(
242+
"ObjectResult.Value",
243+
TestValue,
244+
WrongValue);
245+
246+
Action a = () => result.Should().BeObjectResult().WithValue(TestValue, Reason, ReasonArgs);
247+
248+
a.Should().Throw<Exception>()
249+
.WithMessage(failureMessage);
250+
}
251+
252+
[Fact]
253+
public void WithValueEquivalentTo_GivenExpected_ShouldPass()
254+
{
255+
var result = new ObjectResult(TestObject);
256+
257+
result.Should().BeObjectResult()
258+
.WithValueEquivalentTo(GoodObject);
259+
}
260+
261+
[Fact]
262+
public void WithValueEquivalentTo_GivenUnexpected_ShouldFail()
263+
{
264+
var result = new ObjectResult(WrongObject);
265+
string failureMessage = @"Expected member Value to be
266+
""testValue"" with a length of 9 because it is 10, but
267+
""wrongValue"" has a length of 10.
268+
269+
With configuration:
270+
- Use declared types and members
271+
- Compare enums by value
272+
- Match member by name (or throw)
273+
- Without automatic conversion.
274+
- Be strict about the order of items in byte arrays";
275+
276+
Action a = () => result.Should().BeObjectResult().WithValueEquivalentTo(GoodObject, Reason, ReasonArgs);
277+
278+
a.Should().Throw<Exception>()
279+
.WithMessage(failureMessage);
280+
}
281+
282+
[Fact]
283+
public void WithValueMatch_GivenExpected_ShouldPass()
284+
{
285+
var result = new ObjectResult(TestValue);
286+
287+
result.Should().BeObjectResult()
288+
.WithValueMatch<string>(value => value == TestValue);
289+
}
290+
291+
[Fact]
292+
public void WithValueMatch_GivenUnexpected_ShouldFail()
293+
{
294+
var result = new ObjectResult(WrongValue);
295+
string failureMessage = "Expected ObjectResult.Value to match (value == \"testValue\") because it is 10, but found \"wrongValue\".";
296+
297+
Action a = () => result.Should().BeObjectResult().WithValueMatch<string>(value => value == TestValue, Reason, ReasonArgs);
298+
299+
a.Should().Throw<Exception>()
300+
.WithMessage(failureMessage);
301+
}
302+
222303
}
223304
}

0 commit comments

Comments
 (0)