{"id":13339517,"url":"https://github.com/dimitrietataru/csharp-unit-testing","last_synced_at":"2026-03-15T01:03:00.300Z","repository":{"id":55655353,"uuid":"238185348","full_name":"dimitrietataru/csharp-unit-testing","owner":"dimitrietataru","description":".NET - Unit Testing","archived":false,"fork":false,"pushed_at":"2020-12-15T00:04:45.000Z","size":293,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-17T14:36:30.768Z","etag":null,"topics":["arrange-act-assert","asp-net-core-web-api","assertions","bogus","code-coverage","coverage-report","csharp","dot-net-core","fluentassertions","given-when-then","moqui-framework","net-5","net-core-3-1","nunit-framework","reportgenerator","shouldly","unit-testing","xunit-framework"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dimitrietataru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-04T10:59:59.000Z","updated_at":"2024-11-03T10:21:52.000Z","dependencies_parsed_at":"2022-08-15T05:40:41.155Z","dependency_job_id":null,"html_url":"https://github.com/dimitrietataru/csharp-unit-testing","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimitrietataru%2Fcsharp-unit-testing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimitrietataru%2Fcsharp-unit-testing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimitrietataru%2Fcsharp-unit-testing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimitrietataru%2Fcsharp-unit-testing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimitrietataru","download_url":"https://codeload.github.com/dimitrietataru/csharp-unit-testing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242901084,"owners_count":20203887,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arrange-act-assert","asp-net-core-web-api","assertions","bogus","code-coverage","coverage-report","csharp","dot-net-core","fluentassertions","given-when-then","moqui-framework","net-5","net-core-3-1","nunit-framework","reportgenerator","shouldly","unit-testing","xunit-framework"],"created_at":"2024-07-29T19:20:21.472Z","updated_at":"2025-12-24T01:34:01.933Z","avatar_url":"https://github.com/dimitrietataru.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# C# Unit Testing\n\n![Coverage](https://github.com/dimitrietataru/csharp-unit-testing/blob/master/Coverage.png)\n\n## Table of contents\n\n* [NuGet packages](#nuget-packages)\n* [Syntax](#syntax)\n  * [Given-When-Then](#given-when-then-pattern)\n  * [Arrange-Act-Assert](#arrange-act-assert-pattern)\n  * [Moq](#moq-setup-and-verify)\n  * [Assertions](#assertions)\n* [Collect code coverage](#collect-code-coverage)\n* [Generate code coverage report](#generate-code-coverage-report)\n\n\n## NuGet packages\n- **Frameworks**\n  - [NUnit](https://www.nuget.org/packages/NUnit)\n  - [xUnit](https://www.nuget.org/packages/xunit)\n- **Mocking**\n  - [Moq](https://www.nuget.org/packages/Moq)\n- **Code coverage**\n  - [coverlet.collector](https://www.nuget.org/packages/coverlet.collector)\n  - [ReportGenerator](https://www.nuget.org/packages/ReportGenerator)\n- **Utils**\n  - [Bogus](https://www.nuget.org/packages/Bogus)\n  - [Shouldly](https://www.nuget.org/packages/shouldly)\n  - [FluentAssertions](https://www.nuget.org/packages/FluentAssertions)\n\n``` powershell\nPM\u003e Install-Package Bogus -Version 32.0.2\nPM\u003e Install-Package coverlet.collector -Version 1.3.0\nPM\u003e Install-Package FluentAssertions -Version 5.10.3\nPM\u003e Install-Package Microsoft.NET.Test.Sdk -Version 16.8.3\nPM\u003e Install-Package Moq -Version 4.15.2\nPM\u003e Install-Package ReportGenerator -Version 4.8.1\nPM\u003e Install-Package Shouldly -Version 4.0.1\n\n# NUnit\nPM\u003e Install-Package NUnit -Version 3.12.0\nPM\u003e Install-Package NUnit3TestAdapter -Version 3.17.0\n\n# xUnit\nPM\u003e Install-Package xunit -Version 2.4.1\nPM\u003e Install-Package xunit.runner.visualstudio -Version 2.4.3\n```\n\n\n## Syntax\n\n### Given-When-Then pattern\n[Martin Fowler's blog](https://www.martinfowler.com/bliki/GivenWhenThen.html)\n\n### Arrange-Act-Assert pattern\n[Docs.Microsoft](https://docs.microsoft.com/en-us/visualstudio/test/unit-test-basics?view=vs-2019#write-your-tests)\n\n### Moq setup and verify\n\n``` csharp\n// Setup async method when it returns data\nmockService\n    .Setup(_ =\u003e _.GetAsync(It.IsAny\u003cint\u003e()))\n    .ReturnsAsync(It.IsAny\u003cData\u003e())\n    .Verifiable();\n\n// Setup async method when it executes without a return type\nmockService\n    .Setup(_ =\u003e _.RunAsync())\n    .ReturnsAsync(Task.CompletedTask)\n    .Verifiable();\n\n// Setup async method when it throws an exception\nmockService\n    .Setup(_ =\u003e _.RunAsync(It.IsAny\u003cint\u003e()))\n    .Throws\u003cException\u003e()\n    .Verifiable();\n\n// Verify all service methods, marked as 'Verifiable'\nmockService.VerifyAll();\n\n// Verify individual service method\nmockService.Verify(_ =\u003e _.GetAsync(It.IsAny\u003cint\u003e()), Times.Once);\nmockService.Verify(_ =\u003e _.RunAsync(), Times.Exactly(2));\nmockService.Verify(_ =\u003e _.RunAsync(It.IsAny\u003cint\u003e()), Times.Never);\n```\n\n### Assertions\n\n``` csharp\n// NUnit\nAssert.That(result, Is.InstanceOf\u003cObjectResult\u003e());\nvar apiResponse = result as OkObjectResult;\nAssert.That(apiResponse.StatusCode, Is.EqualTo((int)HttpStatusCode.OK));\n\n// xUnit\nvar apiResponse = Assert.IsType\u003cOkObjectResult\u003e(result);\nAssert.Equal((int)HttpStatusCode.OK, apiResponse.StatusCode);\n\n// FluentAssertions\nresult\n    .Should().BeOfType\u003cOkObjectResult\u003e(\"because we return content\")\n    .Which.StatusCode.Should().Be((int)HttpStatusCode.OK);\n    \n// Shouldly\nresult.ShouldSatisfyAllConditions(\n    () =\u003e result.ShouldBeOfType\u003cOkObjectResult\u003e(),\n    () =\u003e (result as OkObjectResult).StatusCode.ShouldBe((int)HttpStatusCode.OK));\n```\n\n\n## Collect code coverage\n\n### Install *coverlet.collector* NuGet package\n``` powershell\nPM\u003e Install-Package coverlet.collector -Version 1.3.0\n```\n\n### *TestProject.csproj* configuration\n``` xml\n\u003cPackageReference Include=\"coverlet.collector\" Version=\"1.3.0\"\u003e\n  \u003cPrivateAssets\u003eall\u003c/PrivateAssets\u003e\n  \u003cIncludeAssets\u003eruntime; build; native; contentfiles; analyzers; buildtransitive\u003c/IncludeAssets\u003e\n\u003c/PackageReference\u003e\n```\n\n### Collector configuration. Add a file (e.g. *runsettings*) anywhere in the solution/project\n```  xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\" ?\u003e\n\u003cRunSettings\u003e\n  \u003cDataCollectionRunSettings\u003e\n    \u003cDataCollectors\u003e\n      \u003cDataCollector friendlyName=\"XPlat code coverage\"\u003e\n        \u003cConfiguration\u003e\n          \u003cFormat\u003ejson,cobertura\u003c/Format\u003e\n          \u003cUseSourceLink\u003etrue\u003c/UseSourceLink\u003e\n          \u003cIncludeTestAssembly\u003efalse\u003c/IncludeTestAssembly\u003e\n          \u003cExcludeByFile\u003e**/**/Program.cs,**/**/Startup.cs,**/Dir/SubDir/*.cs\u003c/ExcludeByFile\u003e\n        \u003c/Configuration\u003e\n      \u003c/DataCollector\u003e\n    \u003c/DataCollectors\u003e\n  \u003c/DataCollectionRunSettings\u003e\n  \u003cInProcDataCollectionRunSettings\u003e\n    \u003cInProcDataCollectors\u003e\n      \u003cInProcDataCollector\n        assemblyQualifiedName=\"Coverlet.Collector.DataCollection.CoverletInProcDataCollector, coverlet.collector, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null\"\n        friendlyName=\"XPlat Code Coverage\"\n        enabled=\"True\"\n        codebase=\"coverlet.collector.dll\" /\u003e\n    \u003c/InProcDataCollectors\u003e\n  \u003c/InProcDataCollectionRunSettings\u003e\n\u003c/RunSettings\u003e\n```\n\n### Run tests and collect data\n``` powershell\nPM\u003e dotnet test --collect:\"XPlat Code Coverage\" --settings .\\runsettings\n\nPM\u003e dotnet test .\\Specific.Test.Project --collect:\"XPlat Code Coverage\" --settings .\\Specific.Test.Project\\runsettings\n```\n\n\n## Generate Code Coverage Report\n\n### Install *ReportGenerator* NuGet package\n``` powershell\nPM\u003e Install-Package ReportGenerator -Version 4.8.1\n```\n\n### Generate reports\n\n[ReportGenerator usage page](https://danielpalme.github.io/ReportGenerator/usage.html)\n\n``` powershell\nPM\u003e dotnet $(UserProfile)\\.nuget\\packages\\reportgenerator\\x.y.z\\tools\\netcoreapp3.0\\ReportGenerator.dll \"-reports:coverage.xml\" \"-targetdir:coveragereport\" -reporttypes:Html\nPM\u003e dotnet $(UserProfile)\\.nuget\\packages\\reportgenerator\\x.y.z\\tools\\netcoreapp3.0\\ReportGenerator.dll \"-reports:coverage.xml\" \"-targetdir:coveragereport\" -reporttypes:Badges\n```\n``` powershell\n# CSharp.UnitTesting.Api NUnit\nPM\u003e dotnet $(UserProfile)\\.nuget\\packages\\reportgenerator\\4.8.1\\tools\\netcoreapp3.0\\ReportGenerator.dll \"-reports:CSharp.UnitTesting.Api.Nunit.Test\\TestResults\\*\\coverage.cobertura.xml\" \"-targetdir:_CoverageReport\\Api\\NUnit\" \"-historydir:_CoverageReport\\_History\\Api\\NUnit\" -reporttypes:Html\n\n# CSharp.UnitTesting.Api xUnit\nPM\u003e dotnet $(UserProfile)\\.nuget\\packages\\reportgenerator\\4.8.1\\tools\\netcoreapp3.0\\ReportGenerator.dll \"-reports:CSharp.UnitTesting.Api.Xunit.Test\\TestResults\\*\\coverage.cobertura.xml\" \"-targetdir:_CoverageReport\\Api\\xUnit\" \"-historydir:_CoverageReport\\_History\\Api\\xUnit\" -reporttypes:Html\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimitrietataru%2Fcsharp-unit-testing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimitrietataru%2Fcsharp-unit-testing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimitrietataru%2Fcsharp-unit-testing/lists"}