diff --git a/src/FluentAssertions.AspNetCore.Mvc/ActionResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/ActionResultAssertions.cs index 40eadfc..5cb1f6b 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/ActionResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/ActionResultAssertions.cs @@ -86,6 +86,147 @@ public EmptyResult BeEmptyResult(string reason, params object[] reasonArgs) return Subject as EmptyResult; } + /// + /// Asserts that the subject is an . + /// + public FileResultAssertions BeFileResult() + { + return BeFileResult(string.Empty, null); + } + + /// + /// Asserts that the subject is an . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions BeFileResult(string reason, params object[] reasonArgs) + { + Execute.Assertion + .BecauseOf(reason, reasonArgs) + .ForCondition(Subject is FileResult) + .FailWith(Constants.CommonFailMessage, typeof(FileResult).Name, Subject.GetType().Name); + + return new FileResultAssertions(Subject as FileResult); + } + + /// + /// Asserts that the subject is an . + /// + public FileContentResultAssertions BeFileContentResult() + { + return BeFileContentResult(string.Empty, null); + } + + /// + /// Asserts that the subject is an . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileContentResultAssertions BeFileContentResult(string reason, params object[] reasonArgs) + { + Execute.Assertion + .BecauseOf(reason, reasonArgs) + .ForCondition(Subject is FileContentResult) + .FailWith(Constants.CommonFailMessage, typeof(FileContentResult).Name, Subject.GetType().Name); + + return new FileContentResultAssertions(Subject as FileContentResult); + } + + /// + /// Asserts that the subject is an . + /// + internal FileStreamResultAssertions BeFileStreamResult() + { + return BeFileStreamResult(string.Empty, null); + + } + + /// + /// Asserts that the subject is an . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + internal FileStreamResultAssertions BeFileStreamResult(string reason, params object[] reasonArgs) + { + Execute.Assertion + .BecauseOf(reason, reasonArgs) + .ForCondition(Subject is FileStreamResult) + .FailWith(Constants.CommonFailMessage, typeof(FileStreamResult).Name, Subject.GetType().Name); + + return new FileStreamResultAssertions(Subject as FileStreamResult); + } + + /// + /// Asserts that the subject is an . + /// + internal PhysicalFileResultAssertions BePhysicalFileResult() + { + return BePhysicalFileResult(string.Empty, null); + } + + /// + /// Asserts that the subject is an . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + internal PhysicalFileResultAssertions BePhysicalFileResult(string reason, params object[] reasonArgs) + { + Execute.Assertion + .BecauseOf(reason, reasonArgs) + .ForCondition(Subject is PhysicalFileResult) + .FailWith(Constants.CommonFailMessage, typeof(PhysicalFileResult).Name, Subject.GetType().Name); + + return new PhysicalFileResultAssertions(Subject as PhysicalFileResult); + } + + /// + /// Asserts that the subject is an . + /// + internal VirtualFileResultAssertions BeVirtualFileResult() + { + return BeVirtualFileResult(string.Empty, null); + } + + /// + /// Asserts that the subject is an . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + internal VirtualFileResultAssertions BeVirtualFileResult(string reason, params object[] reasonArgs) + { + Execute.Assertion + .BecauseOf(reason, reasonArgs) + .ForCondition(Subject is VirtualFileResult) + .FailWith(Constants.CommonFailMessage, typeof(VirtualFileResult).Name, Subject.GetType().Name); + + return new VirtualFileResultAssertions(Subject as VirtualFileResult); + } + /// /// Asserts that the subject is an . /// diff --git a/src/FluentAssertions.AspNetCore.Mvc/AssertionsExtensions.cs b/src/FluentAssertions.AspNetCore.Mvc/AssertionsExtensions.cs index 93edc5c..7324789 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/AssertionsExtensions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/AssertionsExtensions.cs @@ -1,6 +1,6 @@ -using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; +using System.Diagnostics; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/ContentResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/ContentResultAssertions.cs index 33016f9..567588e 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/ContentResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/ContentResultAssertions.cs @@ -1,7 +1,7 @@ -using System; -using FluentAssertions.Execution; +using FluentAssertions.Execution; using FluentAssertions.Primitives; using Microsoft.AspNetCore.Mvc; +using System; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.Designer.cs b/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.Designer.cs index 06e53f2..963b618 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.Designer.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.Designer.cs @@ -87,6 +87,24 @@ internal static string CommonTypeFailMessage { } } + /// + /// Looks up a localized string similar to Expected "FileContentResult.FileContents" to have {0} byte(s), but found {1}.. + /// + internal static string FileContentResult_WithFileContents_LengthFail { + get { + return ResourceManager.GetString("FileContentResult_WithFileContents_LengthFail", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected "FileContentResult.FileContents[{0}]" to be {1:x2}, but found {2:x2}.. + /// + internal static string FileContentResult_WithFileContents_MatchFail { + get { + return ResourceManager.GetString("FileContentResult_WithFileContents_MatchFail", resourceCulture); + } + } + /// /// Looks up a localized string similar to RedirectToActionResult.RouteValues does not contain key {0}.. /// diff --git a/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.resx b/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.resx index 03209c2..6dccd97 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.resx +++ b/src/FluentAssertions.AspNetCore.Mvc/FailureMessages.resx @@ -126,6 +126,12 @@ Expected {0} to be of type '{1}' but was '{2}' + + Expected "FileContentResult.FileContents" to have {0} byte(s), but found {1}. + + + Expected "FileContentResult.FileContents[{0}]" to be {1:x2}, but found {2:x2}. + RedirectToActionResult.RouteValues does not contain key {0}. diff --git a/src/FluentAssertions.AspNetCore.Mvc/FileContentResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/FileContentResultAssertions.cs new file mode 100644 index 0000000..72e051d --- /dev/null +++ b/src/FluentAssertions.AspNetCore.Mvc/FileContentResultAssertions.cs @@ -0,0 +1,77 @@ +using FluentAssertions.Execution; +using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace FluentAssertions.AspNetCore.Mvc +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// > + [DebuggerNonUserCode] + public class FileContentResultAssertions : FileResultAssertions + { + #region Public Constructors + + public FileContentResultAssertions(FileContentResult fileResult) + : base(fileResult) + { + } + + #endregion + + #region Public Properties + + /// + /// The FileContents on the . + /// + [SuppressMessage("Performance", "CA1819:Properties should not return arrays", + Justification = "It needs to return the same instance as FileContentResult")] + public byte[] FileContents => FileContentResultSubject.FileContents; + + #endregion Private Properties + + #region Private Properties + + private FileContentResult FileContentResultSubject => (FileContentResult)Subject; + + #endregion Private Properties + + #region Public Methods + + /// + /// Asserts that the file contents is the expected bytes. + /// + /// The expected file contents. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + internal FileContentResultAssertions WithFileContents(byte[] expectedFileContents, string reason = "", + params object[] reasonArgs) + { + var actualFileContents = FileContentResultSubject.FileContents; + + Execute.Assertion + .ForCondition(expectedFileContents.Length == actualFileContents.Length) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.FileContentResult_WithFileContents_LengthFail, expectedFileContents.Length, actualFileContents.Length); + for (int i = 0; i < expectedFileContents.Length; i++) + { + var expectedByte = expectedFileContents[i]; + var actualByte = actualFileContents[i]; + Execute.Assertion + .ForCondition(expectedByte == actualByte) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.FileContentResult_WithFileContents_MatchFail, i, expectedByte, actualByte); + } + + return this; + } + + #endregion + } +} diff --git a/src/FluentAssertions.AspNetCore.Mvc/FileResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/FileResultAssertions.cs new file mode 100644 index 0000000..7917b57 --- /dev/null +++ b/src/FluentAssertions.AspNetCore.Mvc/FileResultAssertions.cs @@ -0,0 +1,127 @@ +using FluentAssertions.Execution; +using FluentAssertions.Primitives; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Net.Http.Headers; +using System; +using System.Diagnostics; + +namespace FluentAssertions.AspNetCore.Mvc +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class FileResultAssertions : ObjectAssertions + { + #region Public Constructors + + public FileResultAssertions(FileResult fileResult) + : base(fileResult) + { + } + + #endregion + + #region Private Properties + + private FileResult FileResultSubject => (FileResult)Subject; + + #endregion Private Properties + + #region Public Methods + + /// + /// Asserts that the content type is the expected string. + /// + /// The expected content type. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithContentType(string expectedContentType, string reason = "", + params object[] reasonArgs) + { + var actualContentType = FileResultSubject.ContentType; + + Execute.Assertion + .ForCondition(string.Equals(expectedContentType, actualContentType, StringComparison.OrdinalIgnoreCase)) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "FileResult.ContentType", expectedContentType, actualContentType); + return this; + } + + /// + /// Asserts that the entity tag is the expected value. + /// + /// The expected entity tag value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithEntityTag(EntityTagHeaderValue expectedEntityTag, string reason = "", + params object[] reasonArgs) + { + var actualEntityTag = FileResultSubject.EntityTag; + + Execute.Assertion + .ForCondition(Equals(expectedEntityTag, actualEntityTag)) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "FileResult.EntityTag", expectedEntityTag, actualEntityTag); + return this; + } + + /// + /// Asserts that the file download name is the expected string. + /// + /// The expected file download name. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithFileDownloadName(string expectedFileDownloadName, string reason = "", + params object[] reasonArgs) + { + var actualFileDownloadName = FileResultSubject.FileDownloadName; + + Execute.Assertion + .ForCondition(string.Equals(expectedFileDownloadName, actualFileDownloadName, StringComparison.OrdinalIgnoreCase)) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "FileResult.FileDownloadName", expectedFileDownloadName, actualFileDownloadName); + return this; + } + + /// + /// Asserts that the last modified is the expected DateTimeOffset. + /// + /// The expected last modified value. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithLastModified(DateTimeOffset? expectedLastModified, string reason = "", + params object[] reasonArgs) + { + var actualLastModified = FileResultSubject.LastModified; + + Execute.Assertion + .ForCondition(expectedLastModified == actualLastModified) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "FileResult.LastModified", expectedLastModified, actualLastModified); + return this; + } + + #endregion + } +} diff --git a/src/FluentAssertions.AspNetCore.Mvc/FileStreamResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/FileStreamResultAssertions.cs new file mode 100644 index 0000000..944a7cc --- /dev/null +++ b/src/FluentAssertions.AspNetCore.Mvc/FileStreamResultAssertions.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; +using System.IO; + +namespace FluentAssertions.AspNetCore.Mvc +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// > + [DebuggerNonUserCode] + public class FileStreamResultAssertions : FileResultAssertions + { + #region Public Constructors + + public FileStreamResultAssertions(FileStreamResult fileResult) + : base(fileResult) + { + } + + #endregion + + #region Public Properties + + /// + /// The FileStream on the + /// + public Stream FileStream => FileStreamResultSubject.FileStream; + + #endregion + + #region Private Properties + + private FileStreamResult FileStreamResultSubject => (FileStreamResult)Subject; + + #endregion Private Properties + + } +} diff --git a/src/FluentAssertions.AspNetCore.Mvc/JsonResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/JsonResultAssertions.cs index 25fd404..13d6057 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/JsonResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/JsonResultAssertions.cs @@ -29,12 +29,12 @@ public JsonResultAssertions(JsonResult subject) : base(subject) #region Public Properties /// - /// The serializer settings of the JsonResult. + /// The on the . /// public JsonSerializerSettings SerializerSettings => JsonResultSubject.SerializerSettings; /// - /// The value on the JsonResult + /// The Value on the . /// public object Value => JsonResultSubject.Value; diff --git a/src/FluentAssertions.AspNetCore.Mvc/PartialViewResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/PartialViewResultAssertions.cs index c727677..663bd54 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/PartialViewResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/PartialViewResultAssertions.cs @@ -1,7 +1,7 @@ -using System; -using FluentAssertions.Execution; +using FluentAssertions.Execution; using FluentAssertions.Primitives; using Microsoft.AspNetCore.Mvc; +using System; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/PhysicalFileResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/PhysicalFileResultAssertions.cs new file mode 100644 index 0000000..717bc5f --- /dev/null +++ b/src/FluentAssertions.AspNetCore.Mvc/PhysicalFileResultAssertions.cs @@ -0,0 +1,65 @@ +using FluentAssertions.Execution; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Diagnostics; + +namespace FluentAssertions.AspNetCore.Mvc +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class PhysicalFileResultAssertions : FileResultAssertions + { + #region Public Constructors + + public PhysicalFileResultAssertions(PhysicalFileResult fileResult) + : base(fileResult) + { + } + + #endregion + + #region Public Properties + + /// + /// The FileName on the + /// + public string FileName => PhysicalFileResultSubject.FileName; + + #endregion Private Properties + + #region Private Properties + + private PhysicalFileResult PhysicalFileResultSubject => (PhysicalFileResult)Subject; + + #endregion Private Properties + + #region Public Methods + + /// + /// Asserts that the file name is the expected string. + /// + /// The expected file name. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithFileName(string expectedFileName, string reason = "", + params object[] reasonArgs) + { + var actualFileName = PhysicalFileResultSubject.FileName; + + Execute.Assertion + .ForCondition(string.Equals(expectedFileName, actualFileName, StringComparison.OrdinalIgnoreCase)) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "PhysicalFileResult.FileName", expectedFileName, actualFileName); + return this; + } + + #endregion + } +} diff --git a/src/FluentAssertions.AspNetCore.Mvc/RedirectResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/RedirectResultAssertions.cs index f801ff0..0fba407 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/RedirectResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/RedirectResultAssertions.cs @@ -1,7 +1,7 @@ -using System; -using FluentAssertions.Execution; +using FluentAssertions.Execution; using FluentAssertions.Primitives; using Microsoft.AspNetCore.Mvc; +using System; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/RedirectToActionResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/RedirectToActionResultAssertions.cs index bc60415..8ff023a 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/RedirectToActionResultAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/RedirectToActionResultAssertions.cs @@ -1,7 +1,7 @@ -using System; -using FluentAssertions.Execution; +using FluentAssertions.Execution; using FluentAssertions.Primitives; using Microsoft.AspNetCore.Mvc; +using System; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/RouteDataAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/RouteDataAssertions.cs index a01bb23..fd05edd 100644 --- a/src/FluentAssertions.AspNetCore.Mvc/RouteDataAssertions.cs +++ b/src/FluentAssertions.AspNetCore.Mvc/RouteDataAssertions.cs @@ -1,7 +1,7 @@ -using System.Diagnostics; -using FluentAssertions.Execution; +using FluentAssertions.Execution; using FluentAssertions.Primitives; using Microsoft.AspNetCore.Routing; +using System.Diagnostics; namespace FluentAssertions.AspNetCore.Mvc { diff --git a/src/FluentAssertions.AspNetCore.Mvc/VirtualFileResultAssertions.cs b/src/FluentAssertions.AspNetCore.Mvc/VirtualFileResultAssertions.cs new file mode 100644 index 0000000..36b1c07 --- /dev/null +++ b/src/FluentAssertions.AspNetCore.Mvc/VirtualFileResultAssertions.cs @@ -0,0 +1,65 @@ +using FluentAssertions.Execution; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Diagnostics; + +namespace FluentAssertions.AspNetCore.Mvc +{ + /// + /// Contains a number of methods to assert that a is in the expected state. + /// + [DebuggerNonUserCode] + public class VirtualFileResultAssertions : FileResultAssertions + { + #region Public Constructors + + public VirtualFileResultAssertions(VirtualFileResult fileResult) + : base(fileResult) + { + } + + #endregion + + #region Public Properties + + /// + /// The FileName on the + /// + public string FileName => VirtualFileResultSubject.FileName; + + #endregion Private Properties + + #region Private Properties + + private VirtualFileResult VirtualFileResultSubject => (VirtualFileResult)Subject; + + #endregion Private Properties + + #region Public Methods + + /// + /// Asserts that the file name is the expected string. + /// + /// The expected file name. + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public FileResultAssertions WithFileName(string expectedFileName, string reason = "", + params object[] reasonArgs) + { + var actualFileName = VirtualFileResultSubject.FileName; + + Execute.Assertion + .ForCondition(string.Equals(expectedFileName, actualFileName, StringComparison.OrdinalIgnoreCase)) + .BecauseOf(reason, reasonArgs) + .FailWith(FailureMessages.CommonFailMessage, "VirtualFileResult.FileName", expectedFileName, actualFileName); + return this; + } + + #endregion + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/ActionResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/ActionResultAssertions_Tests.cs index 6658e00..56ca711 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/ActionResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/ActionResultAssertions_Tests.cs @@ -1,3 +1,4 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using System; @@ -22,6 +23,7 @@ public void BeContent_GivenNotContent_ShouldFail() { ActionResult result = new ViewResult(); Action a = () => result.Should().BeContentResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"ContentResult\", but found \"ViewResult\""); } @@ -30,6 +32,7 @@ public void BeContent_GivenNotContent_ShouldFail() public void BeEmpty_GivenEmpty_ShouldPass() { ActionResult result = new EmptyResult(); + result.Should().BeEmptyResult(); } @@ -38,14 +41,112 @@ public void BeEmpty_GivenNotEmpty_ShouldPass() { ActionResult result = new ViewResult(); Action a = () => result.Should().BeEmptyResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"EmptyResult\", but found \"ViewResult\""); } + [Fact] + public void BeFileResult_GivenFileResult_ShouldPass() + { + ActionResult result = TestDataGenerator.CreateFileContentResult(); + + result.Should() + .BeFileResult(); + } + + [Fact] + public void BeFileResult_GivenNotFileResult_ShouldFail() + { + ActionResult result = new ViewResult(); + Action a = () => result.Should().BeFileResult(); + + a.Should().Throw() + .WithMessage("Expected ActionResult to be \"FileResult\", but found \"ViewResult\""); + } + + [Fact] + public void BeFileContentResult_GivenFileContentResult_ShouldPass() + { + ActionResult result = TestDataGenerator.CreateFileContentResult(); + + result.Should() + .BeFileContentResult(); + } + + [Fact] + public void BeFileContentResult_GivenNotFileContentResult_ShouldFail() + { + ActionResult result = new ViewResult(); + Action a = () => result.Should().BeFileContentResult(); + + a.Should().Throw() + .WithMessage("Expected ActionResult to be \"FileContentResult\", but found \"ViewResult\""); + } + + [Fact] + public void BeFileStreamResult_GivenFileStreamResult_ShouldPass() + { + ActionResult result = TestDataGenerator.CreateFileStreamResult(); + + result.Should() + .BeFileStreamResult(); + } + + [Fact] + public void BeFileStreamResult_GivenNotFileStreamResult_ShouldFail() + { + ActionResult result = new ViewResult(); + Action a = () => result.Should().BeFileStreamResult(); + + a.Should().Throw() + .WithMessage("Expected ActionResult to be \"FileStreamResult\", but found \"ViewResult\""); + } + + [Fact] + public void BePhysicalFileResult_GivenPhysicalFileResult_ShouldPass() + { + ActionResult result = TestDataGenerator.CreatePhysicalFileResult(); + + result.Should() + .BePhysicalFileResult(); + } + + [Fact] + public void BePhysicalFileResult_GivenNotPhysicalFileResult_ShouldFail() + { + ActionResult result = new ViewResult(); + Action a = () => result.Should().BePhysicalFileResult(); + + a.Should().Throw() + .WithMessage("Expected ActionResult to be \"PhysicalFileResult\", but found \"ViewResult\""); + } + + [Fact] + public void BeVirtualFileResult_GivenVirtualFileResult_ShouldPass() + { + ActionResult result = TestDataGenerator.CreateVirtualFileResult(); + + result.Should() + .BeVirtualFileResult(); + } + + [Fact] + public void BeVirtualFileResult_GivenNotVirtualFileResult_ShouldFail() + { + ActionResult result = new ViewResult(); + Action a = () => result.Should().BeVirtualFileResult(); + + a.Should().Throw() + .WithMessage("Expected ActionResult to be \"VirtualFileResult\", but found \"ViewResult\""); + } + + [Fact] public void BeJson_GivenJson_ShouldPass() { ActionResult result = new JsonResult(new object()); + result.Should() .BeJsonResult(); } @@ -55,6 +156,7 @@ public void BeJson_GivenNotJson_ShouldFail() { ActionResult result = new ViewResult(); Action a = () => result.Should().BeJsonResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"JsonResult\", but found \"ViewResult\""); } @@ -63,6 +165,7 @@ public void BeJson_GivenNotJson_ShouldFail() public void BeRedirectToRoute_GivenRedirectToRoute_ShouldPass() { ActionResult result = new RedirectToRouteResult(new RouteValueDictionary()); + result.Should().BeRedirectToRouteResult(); } @@ -71,6 +174,7 @@ public void BeRedirectToRoute_GivenNotRedirectToRoute_ShouldFail() { ActionResult result = new ViewResult(); Action a = () => result.Should().BeRedirectToRouteResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"RedirectToRouteResult\", but found \"ViewResult\""); } @@ -79,6 +183,7 @@ public void BeRedirectToRoute_GivenNotRedirectToRoute_ShouldFail() public void BeRedirect_GivenRedirect_ShouldPass() { ActionResult result = new RedirectResult("/"); + result.Should().BeRedirectResult(); } @@ -87,6 +192,7 @@ public void BeRedirect_GivenNotRedirect_ShouldFail() { ActionResult result = new ViewResult(); Action a = () => result.Should().BeRedirectResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"RedirectResult\", but found \"ViewResult\""); } @@ -95,6 +201,7 @@ public void BeRedirect_GivenNotRedirect_ShouldFail() public void BePartialView_GivenPartial_ShouldPass() { ActionResult result = new PartialViewResult(); + result.Should().BePartialViewResult(); } @@ -103,6 +210,7 @@ public void BePartialView_GivenNotPartial_ShouldFail() { ActionResult result = new RedirectResult("/"); Action a = () => result.Should().BePartialViewResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"PartialViewResult\", but found \"RedirectResult\""); } @@ -111,6 +219,7 @@ public void BePartialView_GivenNotPartial_ShouldFail() public void BeView_GivenView_ShouldPass() { ActionResult result = new ViewResult(); + result.Should().BeViewResult(); } @@ -119,6 +228,7 @@ public void BeView_GivenNotView_ShouldFail() { ActionResult result = new RedirectResult("/"); Action a = () => result.Should().BeViewResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"ViewResult\", but found \"RedirectResult\""); } @@ -127,6 +237,7 @@ public void BeView_GivenNotView_ShouldFail() public void BeStatusCodeResult_GivenStatusCodeResult_ShouldPass() { ActionResult result = new StatusCodeResult(200); + result.Should().BeStatusCodeResult(); } @@ -135,6 +246,7 @@ public void BeStatusCodeResult_GivenNotStatusCodeResult_ShouldFail() { ActionResult result = new RedirectResult("/"); Action a = () => result.Should().BeStatusCodeResult(); + a.Should().Throw() .WithMessage("Expected ActionResult to be \"StatusCodeResult\", but found \"RedirectResult\""); } diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/ContentResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/ContentResultAssertions_Tests.cs index fb60b0d..d5c9fba 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/ContentResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/ContentResultAssertions_Tests.cs @@ -1,10 +1,10 @@ -using System; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; +using System; using Xunit; namespace FluentAssertions.AspNetCore.Mvc.Tests { - + public class ContentResultAssertions_Tests { [Fact] diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileContentResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileContentResultAssertions_Tests.cs new file mode 100644 index 0000000..21cb43a --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileContentResultAssertions_Tests.cs @@ -0,0 +1,54 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; +using Microsoft.AspNetCore.Mvc; +using System; +using Xunit; + +namespace FluentAssertions.AspNetCore.Mvc.Tests +{ + public class FileContentResultAssertions_Tests + { + [Fact] + public void WithFileContents_GivenExpectedValue_ShouldPass() + { + var actualBytes = TestDataGenerator.CreateBytes("Test 1"); + var expectedBytes = TestDataGenerator.CreateBytes("Test 1"); + ActionResult result = TestDataGenerator.CreateFileContentResult(actualBytes); + + result.Should() + .BeFileContentResult() + .WithFileContents(expectedBytes); + } + + [Theory] + [InlineData( + "Test 1", "Test 11" + , "Expected \"FileContentResult.FileContents\" to have 7 byte(s), but found 6.")] + [InlineData( + "Test 1a", "Test 2a" + , "Expected \"FileContentResult.FileContents[5]\" to be 0x32, but found 0x31.")] + public void WithFileContents_GivenUnexpectedValue_ShouldFail( + string actual, string expected, string failureMessage) + { + var actualBytes = TestDataGenerator.CreateBytes(actual); + var expectedBytes = TestDataGenerator.CreateBytes(expected); + ActionResult result = TestDataGenerator.CreateFileContentResult(actualBytes); + + Action a = () => result.Should() + .BeFileContentResult() + .WithFileContents(expectedBytes); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + [Fact] + public void FileContents_GivenFileContentResult_ShouldHaveTheSameFileContents() + { + var result = TestDataGenerator.CreateFileContentResult(); + + result.Should() + .BeFileContentResult() + .FileContents.Should().BeSameAs(result.FileContents); + } + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileResultAssertions_Tests.cs new file mode 100644 index 0000000..38cb3a6 --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileResultAssertions_Tests.cs @@ -0,0 +1,118 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; +using FluentAssertions.Mvc.Tests.Helpers; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Net.Http.Headers; +using System; +using Xunit; + +namespace FluentAssertions.AspNetCore.Mvc.Tests +{ + public class FileResultAssertions_Tests + { + [Fact] + public void WithContentType_GivenExpectedValue_ShouldPass() + { + var actualValue = "text/plain"; + var expectedValue = string.Copy(actualValue); + ActionResult result = TestDataGenerator.CreateFileContentResult(contentType: actualValue); + + result.Should().BeFileResult().WithContentType(expectedValue); + } + + [Fact] + public void WithContentType_GivenUnexpected_ShouldFail() + { + var actualValue = "text/css"; + var expectedValue = "text/plain"; + ActionResult result = TestDataGenerator.CreateFileContentResult(contentType: actualValue); + var failureMessage = FailureMessageHelper.Format(FailureMessages.CommonFailMessage, "FileResult.ContentType", expectedValue, actualValue); + + Action a = () => result.Should().BeFileResult().WithContentType(expectedValue); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + [Fact] + public void WithFileDownloadName_GivenExpectedValue_ShouldPass() + { + var result = TestDataGenerator.CreateFileContentResult(); + result.FileDownloadName = "file.txt"; + + result.Should().BeFileResult().WithFileDownloadName("file.txt"); + } + + [Fact] + public void WithFileDownloadName_GivenUnexpected_ShouldFail() + { + var actualValue = "file2.txt"; + var expectedValue = "file1.txt"; + var result = TestDataGenerator.CreateFileContentResult(); + result.FileDownloadName = actualValue; + var failureMessage = FailureMessageHelper.Format(FailureMessages.CommonFailMessage, "FileResult.FileDownloadName", expectedValue, actualValue); + + Action a = () => result.Should().BeFileResult().WithFileDownloadName(expectedValue); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + [Theory] + [InlineData("2009-06-15 13:45:30 -7h")] + [InlineData(null)] + public void WithLastModified_GivenExpectedValue_ShouldPass(string dateText) + { + var result = TestDataGenerator.CreateFileContentResult(); + result.LastModified = TestDataGenerator.CreateDateTimeOffset(dateText); + + result.Should().BeFileResult() + .WithLastModified(TestDataGenerator.CreateDateTimeOffset(dateText)); + } + + [Theory] + [InlineData("2010-07-16 14:46:31 -6h", "2009-06-15 13:45:30 -7h")] + [InlineData(null, "2009-06-15 13:45:30 -7h")] + [InlineData("2010-07-16 14:46:31 -6h", null)] + public void WithLastModified_GivenUnexpected_ShouldFail( + string expected, string actual) + { + var actualValue = TestDataGenerator.CreateDateTimeOffset(actual); + var expectedValue = TestDataGenerator.CreateDateTimeOffset(expected); + var result = TestDataGenerator.CreateFileContentResult(); + result.LastModified = actualValue; + var failureMessage = $"Expected \"FileResult.LastModified\" to be '<{expected ?? "null"}>' but found '<{actual ?? "null"}>'"; + + Action a = () => result.Should().BeFileResult().WithLastModified(expectedValue); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + + [Fact] + public void WithEntityTag_GivenExpectedValue_ShouldPass() + { + var actualValue = new EntityTagHeaderValue("\"sha256 value 1\""); + var expectedValue = new EntityTagHeaderValue("\"sha256 value 1\""); + var result = TestDataGenerator.CreateFileContentResult(); + result.EntityTag = actualValue; + + result.Should().BeFileResult().WithEntityTag(expectedValue); + } + + [Fact] + public void WithEntityTag_GivenUnexpected_ShouldFail() + { + var actualValue = new EntityTagHeaderValue("\"sha256 value 1\"", true); + var expectedValue = new EntityTagHeaderValue("\"sha256 value 2\"", false); + var result = TestDataGenerator.CreateFileContentResult(); + result.EntityTag = actualValue; + var failureMessage = "Expected \"FileResult.EntityTag\" to be '\"sha256 value 2\"' but found 'W/\"sha256 value 1\"'"; + + Action a = () => result.Should().BeFileResult().WithEntityTag(expectedValue); + + a.Should().Throw() + .WithMessage(failureMessage); + } + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileStreamResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileStreamResultAssertions_Tests.cs new file mode 100644 index 0000000..1d9a7a2 --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/FileStreamResultAssertions_Tests.cs @@ -0,0 +1,19 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; +using Xunit; + +namespace FluentAssertions.AspNetCore.Mvc.Tests +{ + public class FileStreamResultAssertions_Tests + { + [Fact] + public void FileStream_GivenFileStreamResult_ShouldHaveTheSameStream() + { + var result = TestDataGenerator.CreateFileStreamResult(); + + result.Should() + .BeFileStreamResult() + .FileStream + .Should().BeSameAs(result.FileStream); + } + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/FailureMessageHelper.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/FailureMessageHelper.cs index 0f88101..7dd6fad 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/FailureMessageHelper.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/FailureMessageHelper.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; namespace FluentAssertions.Mvc.Tests.Helpers { diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/TestDataGenerator.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/TestDataGenerator.cs new file mode 100644 index 0000000..6aaaf2d --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/Helpers/TestDataGenerator.cs @@ -0,0 +1,71 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace FluentAssertions.AspNetCore.Mvc.Tests.Helpers +{ + public static class TestDataGenerator + { + public static FileContentResult CreateFileContentResult(string content = "", string contentType = "text/plain") + { + return CreateFileContentResult(CreateBytes(content), contentType); + } + + public static FileContentResult CreateFileContentResult(byte[] fileContents, string contentType = "text/plain") + { + return new FileContentResult(fileContents, contentType); + } + + public static FileStreamResult CreateFileStreamResult(string content = "") + { + return CreateFileStreamResult(CreateStream(content)); + } + + public static PhysicalFileResult CreatePhysicalFileResult(string fileName = "c:\\temp.txt") + { + return new PhysicalFileResult(fileName, "text/plain"); + } + + public static VirtualFileResult CreateVirtualFileResult(string fileName = "~/temp.txt") + { + return new VirtualFileResult(fileName, "text/plain"); + } + + public static FileStreamResult CreateFileStreamResult(Stream stream) + { + return new FileStreamResult(stream, "text/plain"); + } + + public static Stream CreateStream(string content = "") + { + var memoryStream = new MemoryStream(); + var bytes = CreateBytes(content); + memoryStream.Write(bytes, 0, bytes.Length); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + public static byte[] CreateBytes(string content = "") + { + var bytes = Encoding.UTF8.GetBytes(content); + return bytes; + } + + public static DateTimeOffset? CreateDateTimeOffset(string dateText) + { + if (dateText == null) + return null; + var match = dateRegex.Match(dateText); + return new DateTimeOffset( + DateTime.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture), + TimeSpan.FromHours(int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture))); + } + + private static readonly Regex dateRegex + = new Regex(@"^(\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}) (-?\d+)h$"); + + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/JsonResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/JsonResultAssertions_Tests.cs index 34dc2e3..8d83c28 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/JsonResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/JsonResultAssertions_Tests.cs @@ -9,7 +9,7 @@ namespace FluentAssertions.AspNetCore.Mvc.Tests public class JsonResultAssertions_Tests { [Fact] - public void WithContentType_GivenValue_ShouldPass() + public void WithContentType_GivenExpectedValue_ShouldPass() { ActionResult result = new JsonResult("value") { @@ -37,7 +37,7 @@ public void WithContentType_GivenUnexpected_ShouldFail() } [Fact] - public void WithStatusCode_GivenValue_ShouldPass() + public void WithStatusCode_GivenExpectedValue_ShouldPass() { ActionResult result = new JsonResult("value") { diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/PartialViewResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/PartialViewResultAssertions_Tests.cs index 4765688..ea3a358 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/PartialViewResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/PartialViewResultAssertions_Tests.cs @@ -1,11 +1,11 @@ -using System; -using FluentAssertions.Mvc.Tests.Helpers; +using FluentAssertions.Mvc.Tests.Helpers; using Microsoft.AspNetCore.Mvc; +using System; using Xunit; namespace FluentAssertions.AspNetCore.Mvc.Tests { - + public class PartialViewResultAssertions_Tests { [Fact] diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/PhysicalFileResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/PhysicalFileResultAssertions_Tests.cs new file mode 100644 index 0000000..42fa696 --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/PhysicalFileResultAssertions_Tests.cs @@ -0,0 +1,50 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; +using Microsoft.AspNetCore.Mvc; +using System; +using Xunit; + +namespace FluentAssertions.AspNetCore.Mvc.Tests +{ + public class PhysicalFileResultAssertions_Tests + { + + [Fact] + public void WithFileName_GivenExpectedValue_ShouldPass() + { + var actualFileName = "Test1.txt"; + var expectedFileName = string.Copy(actualFileName); + ActionResult result = TestDataGenerator.CreatePhysicalFileResult(actualFileName); + + result.Should() + .BePhysicalFileResult() + .WithFileName(expectedFileName); + } + + [Fact] + public void WithFileName_GivenUnexpectedValue_ShouldFail() + { + string actualFileName = "Test1.txt"; + string expectedFileName = "Test2.txt"; + ActionResult result = TestDataGenerator.CreatePhysicalFileResult(actualFileName); + var failureMessage = "Expected \"PhysicalFileResult.FileName\" to be '\"Test2.txt\"' but found '\"Test1.txt\"'"; + + Action a = () => result.Should() + .BePhysicalFileResult() + .WithFileName(expectedFileName); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + [Fact] + public void FileName_GivenPhysicalFileResult_ShouldHaveTheFileName() + { + var result = TestDataGenerator.CreatePhysicalFileResult(); + + result.Should() + .BePhysicalFileResult() + .FileName + .Should().BeSameAs(result.FileName); + } + } +} diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectResultAssertions_Tests.cs index c9cf484..4cdda0d 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectResultAssertions_Tests.cs @@ -1,10 +1,10 @@ -using System; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; +using System; using Xunit; namespace FluentAssertions.AspNetCore.Mvc.Tests { - + public class RedirectResultAssertions_Tests { [Fact] diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectToActionResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectToActionResultAssertions_Tests.cs index c01ddc4..889efa7 100644 --- a/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectToActionResultAssertions_Tests.cs +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/RedirectToActionResultAssertions_Tests.cs @@ -1,11 +1,11 @@ -using System; -using FluentAssertions.Mvc.Tests.Helpers; +using FluentAssertions.Mvc.Tests.Helpers; using Microsoft.AspNetCore.Mvc; +using System; using Xunit; namespace FluentAssertions.AspNetCore.Mvc.Tests { - + public class RedirectToActionResultAssertions_Tests { [Fact] diff --git a/tests/FluentAssertions.AspNetCore.Mvc.Tests/VirtualFileResultAssertions_Tests.cs b/tests/FluentAssertions.AspNetCore.Mvc.Tests/VirtualFileResultAssertions_Tests.cs new file mode 100644 index 0000000..e46a973 --- /dev/null +++ b/tests/FluentAssertions.AspNetCore.Mvc.Tests/VirtualFileResultAssertions_Tests.cs @@ -0,0 +1,50 @@ +using FluentAssertions.AspNetCore.Mvc.Tests.Helpers; +using Microsoft.AspNetCore.Mvc; +using System; +using Xunit; + +namespace FluentAssertions.AspNetCore.Mvc.Tests +{ + public class VirtualFileResultAssertions_Tests + { + + [Fact] + public void WithFileName_GivenExpectedValue_ShouldPass() + { + var actualFileName = "Test1.txt"; + var expectedFileName = string.Copy(actualFileName); + ActionResult result = TestDataGenerator.CreateVirtualFileResult(actualFileName); + + result.Should() + .BeVirtualFileResult() + .WithFileName(expectedFileName); + } + + [Fact] + public void WithFileName_GivenUnexpectedValue_ShouldFail() + { + string actualFileName = "Test1.txt"; + string expectedFileName = "Test2.txt"; + ActionResult result = TestDataGenerator.CreateVirtualFileResult(actualFileName); + var failureMessage = "Expected \"VirtualFileResult.FileName\" to be '\"Test2.txt\"' but found '\"Test1.txt\"'"; + + Action a = () => result.Should() + .BeVirtualFileResult() + .WithFileName(expectedFileName); + + a.Should().Throw() + .WithMessage(failureMessage); + } + + [Fact] + public void FileName_GivenVirtualFileResult_ShouldHaveTheFileName() + { + var result = TestDataGenerator.CreateVirtualFileResult(); + + result.Should() + .BeVirtualFileResult() + .FileName + .Should().BeSameAs(result.FileName); + } + } +}