{"id":146,"date":"2020-04-16T15:29:28","date_gmt":"2020-04-16T14:29:28","guid":{"rendered":"https:\/\/wissing.me\/?p=146"},"modified":"2020-04-16T15:29:28","modified_gmt":"2020-04-16T14:29:28","slug":"unit-testing-file-input","status":"publish","type":"post","link":"https:\/\/daan.wsng.eu\/index.php\/2020\/04\/16\/unit-testing-file-input\/","title":{"rendered":"Unit testing file input"},"content":{"rendered":"<p>Unit tests are mandatory for any business logic. But what if your business logic is parsing and processing files? Then you will need files as input in your tests.<\/p>\n<p>At first, I thought about making an extra wrapper around reading the file and mocking the wrapper when parsing it. However, sometimes this is more complicated than necessary. Plus, using actual files has more benefits. For example, if in Production you have a file that gives unexpected results, you can use that exact file in a new unit test, and then fix\/change the behavior using Test Driven Development. Or when you use a third-party tool to read the data, and mocking that third-party tool is not feasible.<\/p>\n<p>So, here is a simple example. Say we process our files with the following code:<\/p>\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System;\nusing System.IO;\n\nnamespace ProcessFile\n{\n    public class ProcessFile\n    {\n    \tpublic ProcessResult Process(string fileName)\n    \t{\n\t\t\tif (!File.Exists(fileName)) \n\t\t\t\tthrow new ArgumentException($&quot;File {fileName} does not exist&quot;, nameof(fileName));\n\t\t\t\/\/ Process file here...\n    \t\treturn new ProcessResult(); \n    \t}\n\n    \tpublic ProcessResult Process(Stream fileStream)\n    \t{\n\t\t\tif (!fileStream.CanRead)\n\t\t\t\tthrow new ArgumentException(&quot;Stream cannot be read&quot;, nameof(fileStream));\n\t\t\t\/\/ Process stream here...\n    \t\treturn new ProcessResult();\n    \t}\n    }\n}\n<\/pre><\/div>\n\n\n<p>There are two functions here that need to be covered: one function that takes a file location, and one function that takes a stream. Both very reasonable examples. The actual business logic is left out because it is not relevant for now. <\/p>\n\n\n\n<h2>Physical file<\/h2>\n\n\n\n<p>The first test looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#91;Test]\npublic void GivenFile_WhenProcess_ThenResult()\n{\n    \/\/ Given\n    var target = new ProcessFile.ProcessFile();\n    var testLocation = Assembly.GetExecutingAssembly().Location;\n\n    var fileLocation = Path.Combine(Path.GetDirectoryName(testLocation), &quot;TestFiles\/TestFile.csv&quot;);\n    \/\/ When\n    var result = target.Process(fileLocation);\n\n    \/\/ Then\n    Assert.Pass();\n}\n<\/pre><\/div>\n\n\n<p>The actual file is added to the test project. Make sure to set the property <code>CopyToOutputDirectory<\/code> to either <code>Always<\/code> or <code>PreserveNewest<\/code> in the Project file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;ItemGroup&gt;\n    &lt;None Include=&quot;TestFiles\/TestFile.csv&quot; CopyToOutputDirectory=&quot;PreserveNewest&quot; \/&gt;\n&lt;\/ItemGroup&gt;\n<\/pre><\/div>\n\n\n<p>The line <code>Assembly.GetExecutingAssembly().Location<\/code> will give the location of the test assembly dll, which is then used to get the full location to the file we want to test.<\/p>\n\n\n\n<h2>Stream<\/h2>\n\n\n\n<p>The test for the stream looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#91;Test]\npublic void GivenStream_WhenProcess_ThenResult()\n{\n    \/\/ Given\n    var target = new ProcessFile.ProcessFile();\n    var assembly = Assembly.GetExecutingAssembly();\n    var stream = assembly.GetManifestResourceStream(&quot;ProcessFileTests.TestFiles.TestFileEmbedded.csv&quot;);\n\n    \/\/ When\n    var result = target.Process(stream);\n\n    \/\/ Then\n    Assert.Pass();\n}\n<\/pre><\/div>\n\n\n<p>Again, the actual file is added to the project, but as an embedded resource. In the project file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;ItemGroup&gt;\n    &lt;EmbeddedResource Include=&quot;TestFiles\/TestFileEmbedded.csv&quot; CopyToOutputDirectory=&quot;None&quot; \/&gt;\n&lt;\/ItemGroup&gt;\n<\/pre><\/div>\n\n\n<p>Using the testing assembly again, we retrieve the resource using its identifier: <code>ProcessFileTests.TestFiles.TestFileEmbedded.csv<\/code>. This identifier is created automatically when building: it uses the project namespace plus the relative path, where the directories are notated with a . instead of a \/<\/p>\n\n\n\n<h2>Summary<\/h2>\n\n\n\n<p>So, there you have it: two ways to use files as input for unit testing: one with physical files and one with streams. Files are enclosed in the test project and delivered directly to the code to test.<\/p>\n\n\n\n<p>I put all of this code on GitHub by the way: <a href=\"https:\/\/github.com\/daanwissing\/blog-examples\/tree\/master\/unit-test-files\">https:\/\/github.com\/daanwissing\/blog-examples\/tree\/master\/unit-test-files<\/a>. My intention is to do this with all future blogs, and maybe with previous blogs as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unit tests are mandatory for any business logic. But what if your business logic is parsing and processing files? Then you will need files as input in your tests. At first, I thought about making an extra wrapper around reading the file and mocking the wrapper when parsing it. However, sometimes this is more complicated&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"twitterCardType":"","cardImageID":0,"cardImage":"","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[6,10],"tags":[],"_links":{"self":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/146"}],"collection":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/comments?post=146"}],"version-history":[{"count":10,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/146\/revisions"}],"predecessor-version":[{"id":157,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/146\/revisions\/157"}],"wp:attachment":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/media?parent=146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/categories?post=146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/tags?post=146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}