Skip to content

Commit f9348d5

Browse files
committed
Implement ObjectResultAssertions.ContainsContentType
1 parent 46be55d commit f9348d5

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

src/FluentAssertions.AspNetCore.Mvc/ObjectResultAssertionsBase.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace FluentAssertions.AspNetCore.Mvc
1212
/// <summary>
1313
/// Base class for <see cref="ObjectResultAssertions"/>.
1414
/// </summary>
15-
//[DebuggerNonUserCode]
15+
[DebuggerNonUserCode]
1616
public class ObjectResultAssertionsBase<TObjectResult, TObjectResultAssertion> : ObjectAssertions
1717
where TObjectResult : ObjectResult
1818
where TObjectResultAssertion : ObjectResultAssertionsBase<TObjectResult, TObjectResultAssertion>
@@ -108,6 +108,38 @@ public TObjectResultAssertion ContainsFormatter(Expression<Func<IOutputFormatter
108108

109109
return (TObjectResultAssertion)this;
110110
}
111+
112+
/// <summary>
113+
/// Asserts that the <see cref="ObjectResult.ContentTypes"/> contains the specified content type.
114+
/// </summary>
115+
/// <param name="expected">The expectation content type.</param>
116+
/// <param name="reason">
117+
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
118+
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
119+
/// </param>
120+
/// <param name="reasonArgs">
121+
/// Zero or more objects to format using the placeholders in <paramref name="reason"/>.
122+
/// </param>
123+
public TObjectResultAssertion ContainsContentType(string expected, string reason = "", params object[] reasonArgs)
124+
{
125+
var formatters = ObjectResultSubject.ContentTypes;
126+
127+
if (formatters is null)
128+
{
129+
Execute.Assertion
130+
.BecauseOf(reason, reasonArgs)
131+
.WithDefaultIdentifier(Identifier + ".ContentTypes")
132+
.FailWith("Expected {context} to contain {0}{reason} but found {1}.", expected, formatters);
133+
}
134+
135+
Execute.Assertion
136+
.ForCondition(formatters.Contains(expected))
137+
.WithDefaultIdentifier(Identifier + ".ContentTypes")
138+
.BecauseOf(reason, reasonArgs)
139+
.FailWith("Expected {context} {0} to contain {1}{reason}.", formatters, expected);
140+
141+
return (TObjectResultAssertion)this;
142+
}
111143
#endregion
112144

113145
}

tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/FailureMessageHelper.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,21 @@ private static object ToString(DateTimeOffset? expected)
7171
return "<null>";
7272
}
7373

74-
internal static string ExpectedToContainItemButFoundNull(string context, string predicate)
74+
internal static string ExpectedToContainItemButFoundNull(string context, object item)
7575
{
76-
return $"Expected {context} to contain {predicate} because it is 10 but found <null>.";
76+
return $"Expected {context} to contain {Formatter.ToString(item)} because it is 10 but found <null>.";
7777
}
7878

7979
internal static string ExpectedToHaveItemMatching(string context, object list, string predicate)
8080
{
8181
return $"Expected {context} {Formatter.ToString(list)} to have an item matching {predicate} because it is 10.";
8282
}
8383

84+
internal static string ExpectedToContainItem(string context, object list, string expected)
85+
{
86+
return $"Expected {context} {Formatter.ToString(list)} to contain {Formatter.ToString(expected)} because it is 10.";
87+
}
88+
8489
internal static string ExpectedContextTypeXButFoundY(string context, Type expected, Type actual)
8590
{
8691
return ExpectedContextTypeXButFoundY(context, expected.FullName, actual.FullName);

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

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Linq.Expressions;
3+
using System.Net.Http.Headers;
24
using FluentAssertions.Mvc.Tests.Helpers;
35
using Microsoft.AspNetCore.Mvc;
46
using Microsoft.AspNetCore.Mvc.Formatters;
@@ -73,11 +75,12 @@ public void ContainsFormatter_OnNullFormatters_ShouldFail()
7375
{
7476
Formatters = null
7577
};
78+
Expression<Func<IOutputFormatter, bool>> expectation = formatter => formatter == null;
7679
string failureMessage = FailureMessageHelper.ExpectedToContainItemButFoundNull(
7780
"ObjectResult.Formatters",
78-
"(formatter == null)");
81+
expectation.Body);
7982

80-
Action a = () => result.Should().BeObjectResult().ContainsFormatter(formatter => formatter == null, Reason, ReasonArgs);
83+
Action a = () => result.Should().BeObjectResult().ContainsFormatter(expectation, Reason, ReasonArgs);
8184

8285
a.Should().Throw<Exception>()
8386
.WithMessage(failureMessage);
@@ -102,5 +105,60 @@ public void ContainsFormatter_GivenUnexpected_ShouldFail()
102105
.WithMessage(failureMessage);
103106
}
104107

108+
109+
110+
111+
112+
113+
[Fact]
114+
public void ContainsContentType_GivenExpected_ShouldPass()
115+
{
116+
var mediaType = "text/html";
117+
var result = new ObjectResult(TestValue)
118+
{
119+
ContentTypes = { mediaType }
120+
};
121+
122+
result.Should().BeObjectResult().ContainsContentType(mediaType);
123+
}
124+
#if NETCOREAPP2_1
125+
// In NetCore3.1 ContentTypes cant be null.
126+
[Fact]
127+
public void ContainsContentType_OnNullMediaType_ShouldFail()
128+
{
129+
var expected = "text/json";
130+
var result = new ObjectResult(TestValue)
131+
{
132+
ContentTypes = null
133+
};
134+
string failureMessage = FailureMessageHelper.ExpectedToContainItemButFoundNull(
135+
"ObjectResult.ContentTypes",
136+
expected);
137+
138+
Action a = () => result.Should().BeObjectResult().ContainsContentType(expected, Reason, ReasonArgs);
139+
140+
a.Should().Throw<Exception>()
141+
.WithMessage(failureMessage);
142+
}
143+
#endif
144+
[Fact]
145+
public void ContainsContentType_GivenUnexpected_ShouldFail()
146+
{
147+
var mediaType = "text/html";
148+
var expected = "text/json";
149+
var result = new ObjectResult(TestValue)
150+
{
151+
ContentTypes = { mediaType }
152+
};
153+
string failureMessage = FailureMessageHelper.ExpectedToContainItem(
154+
"ObjectResult.ContentTypes",
155+
result.ContentTypes,
156+
expected);
157+
158+
Action a = () => result.Should().BeObjectResult().ContainsContentType(expected, Reason, ReasonArgs);
159+
160+
a.Should().Throw<Exception>()
161+
.WithMessage(failureMessage);
162+
}
105163
}
106164
}

0 commit comments

Comments
 (0)