Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

dimitrietataru/csharp-unit-testing

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C# Unit Testing

Coverage

Table of contents

NuGet packages

PM> Install-Package Bogus -Version 32.0.2
PM> Install-Package coverlet.collector -Version 1.3.0
PM> Install-Package FluentAssertions -Version 5.10.3
PM> Install-Package Microsoft.NET.Test.Sdk -Version 16.8.3
PM> Install-Package Moq -Version 4.15.2
PM> Install-Package ReportGenerator -Version 4.8.1
PM> Install-Package Shouldly -Version 4.0.1

# NUnit
PM> Install-Package NUnit -Version 3.12.0
PM> Install-Package NUnit3TestAdapter -Version 3.17.0

# xUnit
PM> Install-Package xunit -Version 2.4.1
PM> Install-Package xunit.runner.visualstudio -Version 2.4.3

Syntax

Given-When-Then pattern

Martin Fowler's blog

Arrange-Act-Assert pattern

Docs.Microsoft

Moq setup and verify

// Setup async method when it returns data
mockService
    .Setup(_ => _.GetAsync(It.IsAny<int>()))
    .ReturnsAsync(It.IsAny<Data>())
    .Verifiable();

// Setup async method when it executes without a return type
mockService
    .Setup(_ => _.RunAsync())
    .ReturnsAsync(Task.CompletedTask)
    .Verifiable();

// Setup async method when it throws an exception
mockService
    .Setup(_ => _.RunAsync(It.IsAny<int>()))
    .Throws<Exception>()
    .Verifiable();

// Verify all service methods, marked as 'Verifiable'
mockService.VerifyAll();

// Verify individual service method
mockService.Verify(_ => _.GetAsync(It.IsAny<int>()), Times.Once);
mockService.Verify(_ => _.RunAsync(), Times.Exactly(2));
mockService.Verify(_ => _.RunAsync(It.IsAny<int>()), Times.Never);

Assertions

// NUnit
Assert.That(result, Is.InstanceOf<ObjectResult>());
var apiResponse = result as OkObjectResult;
Assert.That(apiResponse.StatusCode, Is.EqualTo((int)HttpStatusCode.OK));

// xUnit
var apiResponse = Assert.IsType<OkObjectResult>(result);
Assert.Equal((int)HttpStatusCode.OK, apiResponse.StatusCode);

// FluentAssertions
result
    .Should().BeOfType<OkObjectResult>("because we return content")
    .Which.StatusCode.Should().Be((int)HttpStatusCode.OK);
    
// Shouldly
result.ShouldSatisfyAllConditions(
    () => result.ShouldBeOfType<OkObjectResult>(),
    () => (result as OkObjectResult).StatusCode.ShouldBe((int)HttpStatusCode.OK));

Collect code coverage

Install coverlet.collector NuGet package

PM> Install-Package coverlet.collector -Version 1.3.0

TestProject.csproj configuration

<PackageReference Include="coverlet.collector" Version="1.3.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Collector configuration. Add a file (e.g. runsettings) anywhere in the solution/project

<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="XPlat code coverage">
        <Configuration>
          <Format>json,cobertura</Format>
          <UseSourceLink>true</UseSourceLink>
          <IncludeTestAssembly>false</IncludeTestAssembly>
          <ExcludeByFile>**/**/Program.cs,**/**/Startup.cs,**/Dir/SubDir/*.cs</ExcludeByFile>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
  <InProcDataCollectionRunSettings>
    <InProcDataCollectors>
      <InProcDataCollector
        assemblyQualifiedName="Coverlet.Collector.DataCollection.CoverletInProcDataCollector, coverlet.collector, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null"
        friendlyName="XPlat Code Coverage"
        enabled="True"
        codebase="coverlet.collector.dll" />
    </InProcDataCollectors>
  </InProcDataCollectionRunSettings>
</RunSettings>

Run tests and collect data

PM> dotnet test --collect:"XPlat Code Coverage" --settings .\runsettings

PM> dotnet test .\Specific.Test.Project --collect:"XPlat Code Coverage" --settings .\Specific.Test.Project\runsettings

Generate Code Coverage Report

Install ReportGenerator NuGet package

PM> Install-Package ReportGenerator -Version 4.8.1

Generate reports

ReportGenerator usage page

PM> dotnet $(UserProfile)\.nuget\packages\reportgenerator\x.y.z\tools\netcoreapp3.0\ReportGenerator.dll "-reports:coverage.xml" "-targetdir:coveragereport" -reporttypes:Html
PM> dotnet $(UserProfile)\.nuget\packages\reportgenerator\x.y.z\tools\netcoreapp3.0\ReportGenerator.dll "-reports:coverage.xml" "-targetdir:coveragereport" -reporttypes:Badges
# CSharp.UnitTesting.Api NUnit
PM> 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

# CSharp.UnitTesting.Api xUnit
PM> 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
Morty Proxy This is a proxified and sanitized view of the page, visit original site.