{"id":4647,"date":"2017-10-12T04:54:23","date_gmt":"2017-10-12T04:54:23","guid":{"rendered":"http:\/\/a1webdesignteam.com\/blog\/?p=4647"},"modified":"2017-10-12T04:54:23","modified_gmt":"2017-10-12T04:54:23","slug":"unit-testing-c-in-net-core-using-dotnet-test-and-xunit","status":"publish","type":"post","link":"https:\/\/a1webdesignteam.com\/blog\/unit-testing-c-in-net-core-using-dotnet-test-and-xunit\/","title":{"rendered":"Unit testing C# in .NET Core using dotnet test and xUnit"},"content":{"rendered":"<h2 id=\"creating-the-source-project\" class=\"\">Creating the source project<\/h2>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"0fc56de9d5b9e2fd9bcd9c4a0d063771:0\">Open a shell window. Create a directory called <em>unit-testing-using-dotnet-test<\/em> to hold the solution. Inside this new directory, run <code>dotnet new sln<\/code> to create a new solution. This makes it easier to manage both the class library and the unit test project. Inside the solution directory, create a <em>PrimeService<\/em> directory. The directory and file structure thus far is shown below:<\/p>\n<div class=\"codeHeader\" data-bi-name=\"code-header\"><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code data-bi-name=\"code-block\">\/unit-testing-using-dotnet-test\r\n    unit-testing-using-dotnet-test.sln\r\n    \/PrimeService\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"07c46c0b4eb3e8790a2989dcc165b771:0\">Make <em>PrimeService<\/em> the current directory and run <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-new\" data-linktype=\"relative-path\"><code>dotnet new classlib<\/code><\/a> to create the source project. Rename <em>Class1.cs<\/em> to <em>PrimeService.cs<\/em>. To use test-driven development (TDD), you&#8217;ll create a failing implementation of the <code>PrimeService<\/code> class:<\/p>\n<div class=\"codeHeader lang-csharp\" data-bi-name=\"code-header\"><span class=\"language\">C#<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-csharp\" data-bi-name=\"code-block\"><span class=\"hljs-keyword\">using<\/span> System;\r\n\r\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">Prime.Services<\/span>\r\n{\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PrimeService<\/span>\r\n    {\r\n        <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">bool<\/span> <span class=\"hljs-title\">IsPrime<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> candidate<\/span>) \r\n        <\/span>{\r\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> NotImplementedException(<span class=\"hljs-string\">\"Please create a test first\"<\/span>);\r\n        } \r\n    }\r\n}\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"0d842a694dbf6afd5b0da0c32502d730:0\">Change the directory back to the <em>unit-testing-using-dotnet-test<\/em> directory. Run <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-sln\" data-linktype=\"relative-path\"><code>dotnet sln add .\\PrimeService\\PrimeService.csproj<\/code><\/a> to add the class library project to the solution.<\/p>\n<h2 id=\"creating-the-test-project\">Creating the test project<\/h2>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"1fc82d6d9dba647b3f89fc63e183c357:0\">Next, create the <em>PrimeService.Tests<\/em> directory. The following outline shows the directory structure:<\/p>\n<div class=\"codeHeader\" data-bi-name=\"code-header\"><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code data-bi-name=\"code-block\">\/unit-testing-using-dotnet-test\r\n    unit-testing-using-dotnet-test.sln\r\n    \/PrimeService\r\n        Source Files\r\n        PrimeService.csproj\r\n    \/PrimeService.Tests\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"0fc46f6d5b997ed93b0fcc434d2702d2:0\">Make the <em>PrimeService.Tests<\/em> directory the current directory and create a new project using <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-new\" data-linktype=\"relative-path\"><code>dotnet new xunit<\/code><\/a>. This creates a test project that uses xUnit as the test library. The generated template configures the test runner in the <em>PrimeServiceTests.csproj<\/em>:<\/p>\n<div class=\"codeHeader lang-xml\" data-bi-name=\"code-header\"><span class=\"language\">XML<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-xml\" data-bi-name=\"code-block\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ItemGroup<\/span>&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PackageReference<\/span> <span class=\"hljs-attr\">Include<\/span>=<span class=\"hljs-string\">\"Microsoft.NET.Test.Sdk\"<\/span> <span class=\"hljs-attr\">Version<\/span>=<span class=\"hljs-string\">\"15.3.0-preview-20170628-02\"<\/span> \/&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PackageReference<\/span> <span class=\"hljs-attr\">Include<\/span>=<span class=\"hljs-string\">\"xunit\"<\/span> <span class=\"hljs-attr\">Version<\/span>=<span class=\"hljs-string\">\"2.2.0\"<\/span> \/&gt;<\/span>\r\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PackageReference<\/span> <span class=\"hljs-attr\">Include<\/span>=<span class=\"hljs-string\">\"xunit.runner.visualstudio\"<\/span> <span class=\"hljs-attr\">Version<\/span>=<span class=\"hljs-string\">\"2.2.0\"<\/span> \/&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ItemGroup<\/span>&gt;<\/span>\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"87e46d6f5dbd6ed93a4f884245020353:0\">The test project requires other packages to create and run unit tests. <code>dotnet new<\/code> in the previous step added xUnit and the xUnit runner. Now, add the <code>PrimeService<\/code> class library as another dependency to the project. Use the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-add-reference\" data-linktype=\"relative-path\"><code>dotnet add reference<\/code><\/a> command:<\/p>\n<div class=\"codeHeader\" data-bi-name=\"code-header\"><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code data-bi-name=\"code-block\">dotnet add reference ..\/PrimeService\/PrimeService.csproj\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"0fe10c09df1666ee104bb00743415a56:0\">You can see the entire file in the <a href=\"https:\/\/github.com\/dotnet\/docs\/blob\/master\/samples\/core\/getting-started\/unit-testing-using-dotnet-test\/PrimeService.Tests\/PrimeService.Tests.csproj\" data-linktype=\"external\">samples repository<\/a> on GitHub.<\/p>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"0f142cacf799e6533bb52863c343e3d7:0\">The following shows the final solution layout:<\/p>\n<div class=\"codeHeader\" data-bi-name=\"code-header\"><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code data-bi-name=\"code-block\">\/unit-testing-using-dotnet-test\r\n    unit-testing-using-dotnet-test.sln\r\n    \/PrimeService\r\n        Source Files\r\n        PrimeService.csproj\r\n    \/PrimeService.Tests\r\n        Test Source Files\r\n        PrimeServiceTests.csproj\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"ae8cedc87dbe4af55a0bc6e1a0db1367:0\">Execute <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-sln\" data-linktype=\"relative-path\"><code>dotnet sln add .\\PrimeService.Tests\\PrimeService.Tests.csproj<\/code><\/a> in the <em>unit-testing-using-dotnet-test<\/em> directory.<\/p>\n<h2 id=\"creating-the-first-test\">Creating the first test<\/h2>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"8dc46d6c9d196e5f1309c84300c33330:0\">The TDD approach calls for writing one failing test, making it pass, then repeating the process. Remove <em>UnitTest1.cs<\/em> from the <em>PrimeService.Tests<\/em> directory and create a new C# file named <em>PrimeService_IsPrimeShould.cs<\/em>. Add the following code:<\/p>\n<div class=\"codeHeader lang-csharp\" data-bi-name=\"code-header\"><span class=\"language\">C#<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-csharp\" data-bi-name=\"code-block\"><span class=\"hljs-keyword\">using<\/span> Xunit;\r\n<span class=\"hljs-keyword\">using<\/span> Prime.Services;\r\n\r\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">Prime.UnitTests.Services<\/span>\r\n{\r\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PrimeService_IsPrimeShould<\/span>\r\n    {\r\n        <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> PrimeService _primeService;\r\n\r\n        <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PrimeService_IsPrimeShould<\/span>()\r\n        <\/span>{\r\n            _primeService = <span class=\"hljs-keyword\">new<\/span> PrimeService();\r\n        }\r\n\r\n        [<span class=\"hljs-meta\">Fact<\/span>]\r\n        <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">ReturnFalseGivenValueOf1<\/span>()\r\n        <\/span>{\r\n            <span class=\"hljs-keyword\">var<\/span> result = _primeService.IsPrime(<span class=\"hljs-number\">1<\/span>);\r\n\r\n            Assert.False(result, <span class=\"hljs-string\">\"1 should not be prime\"<\/span>);\r\n        }\r\n    }\r\n}\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"8b8c6bcd579156f92a4cce8345234577:0\">The <code>[Fact]<\/code> attribute indicates a test method that is run by the test runner. From the <em>unit-testing-using-dotnet-test<\/em>, execute <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-test\" data-linktype=\"relative-path\"><code>dotnet test<\/code><\/a> to build the tests and the class library and then run the tests. The xUnit test runner contains the program entry point to run your tests. <code>dotnet test<\/code> starts the test runner using the unit test project you&#8217;ve created.<span class=\"lf-has-num lf-thread-btn\"><a class=\"fycon-action-view\" tabindex=\"0\" aria-label=\"Write a Sidenote\" data-lf-anchor-id=\"8b8c6bcd579156f92a4cce8345234577:0\">1<\/a><\/span><\/p>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"8bd02f4d4f9844b20129cb03230c1677:0\">Your test fails. You haven&#8217;t created the implementation yet. Make this test by writing the simplest code in the <code>PrimeService<\/code> class that works:<\/p>\n<div class=\"codeHeader lang-csharp\" data-bi-name=\"code-header\"><span class=\"language\">C#<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-csharp\" data-bi-name=\"code-block\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">bool<\/span> <span class=\"hljs-title\">IsPrime<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> candidate<\/span>)\r\n<\/span>{\r\n    <span class=\"hljs-keyword\">if<\/span> (candidate == <span class=\"hljs-number\">1<\/span>)\r\n    {\r\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>;\r\n    }\r\n    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> NotImplementedException(<span class=\"hljs-string\">\"Please create a test first\"<\/span>);\r\n}\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"8dc42f89673942f73a0ec88b65671677:0\">In the <em>unit-testing-using-dotnet-test<\/em> directory, run <code>dotnet test<\/code> again. The <code>dotnet test<\/code> command runs a build for the <code>PrimeService<\/code> project and then for the <code>PrimeService.Tests<\/code> project. After building both projects, it runs this single test. It passes.<\/p>\n<h2 id=\"adding-more-features\">Adding more features<\/h2>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"01d8654ce3b023151aed9982cf2e37e3:0\">Now that you&#8217;ve made one test pass, it&#8217;s time to write more. There are a few other simple cases for prime numbers: 0, -1. You could add those cases as new tests with the <code>[Fact]<\/code> attribute, but that quickly becomes tedious. There are other xUnit attributes that enable you to write a suite of similar tests. A <code>[Theory]<\/code> attribute represents a suite of tests that execute the same code but have different input arguments. You can use the <code>[InlineData]<\/code> attribute to specify values for those inputs.<\/p>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"abe86515e3912e911768dc41c61702c1:0\">Instead of creating new tests, apply these two attributes to create a single theory. The theory is a method that tests several values less than two, which is the lowest prime number:<\/p>\n<div class=\"codeHeader lang-csharp\" data-bi-name=\"code-header\"><span class=\"language\">C#<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-csharp\" data-src=\"https:\/\/github.com\/dotnet\/docs\/blob\/live\/samples\/core\/getting-started\/unit-testing-using-dotnet-test\/PrimeService.Tests\/PrimeService_IsPrimeShould.cs\" data-bi-name=\"code-block\">[<span class=\"hljs-meta\">Theory<\/span>]\r\n[<span class=\"hljs-meta\">InlineData(-1)<\/span>]\r\n[<span class=\"hljs-meta\">InlineData(0)<\/span>]\r\n[<span class=\"hljs-meta\">InlineData(1)<\/span>]\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">ReturnFalseGivenValuesLessThan2<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-keyword\">value<\/span><\/span>)\r\n<\/span>{\r\n    <span class=\"hljs-keyword\">var<\/span> result = _primeService.IsPrime(<span class=\"hljs-keyword\">value<\/span>);\r\n    \r\n    Assert.False(result, <span class=\"hljs-string\">$\"<span class=\"hljs-subst\">{<span class=\"hljs-keyword\">value<\/span>}<\/span> should not be prime\"<\/span>);\r\n}\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"ab9c2d47d7b906d12b28c8414507c273:0\">Run <code>dotnet test<\/code>, and two of these tests fail. To make all of the tests pass, change the <code>if<\/code> clause at the beginning of the method:<\/p>\n<div class=\"codeHeader lang-csharp\" data-bi-name=\"code-header\"><span class=\"language\">C#<\/span><button class=\"action copy\" data-bi-name=\"copy\">Copy<\/button><\/div>\n<pre><code class=\"lang-csharp\" data-bi-name=\"code-block\"><span class=\"hljs-keyword\">if<\/span> (candidate &lt; <span class=\"hljs-number\">2<\/span>)\r\n<\/code><\/pre>\n<p class=\"lf-text-block lf-block\" data-lf-anchor-id=\"8fd6ad65d79c74d9320ba863410b4f5d:0\">Continue to iterate by adding more tests, more theories, and more code in the main library. You have the <a href=\"https:\/\/github.com\/dotnet\/docs\/blob\/master\/samples\/core\/getting-started\/unit-testing-using-dotnet-test\/PrimeService.Tests\/PrimeService_IsPrimeShould.cs\" data-linktype=\"external\">finished version of the tests<\/a> and the complete implementation of the library.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating the source project Open a shell window. Create a directory called unit-testing-using-dotnet-test to hold the solution. Inside this new directory, run dotnet new sln to create a new solution. This makes it easier to manage both the class library and the unit test project. Inside the solution directory, create a PrimeService directory. The directory [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4648,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0},"categories":[32],"tags":[51],"_links":{"self":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4647"}],"collection":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/comments?post=4647"}],"version-history":[{"count":0,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4647\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media\/4648"}],"wp:attachment":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media?parent=4647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/categories?post=4647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/tags?post=4647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}