C#单元测试(xUnit + Moq + coverlet.collector)

发布于:2025-08-17 ⋅ 阅读:(13) ⋅ 点赞:(0)

C#单元测试

xUnit + Moq + coverlet.collector

1.添加库

MlyMathLib

2.编写库函数内容

using System;

namespace MlyMathLib
{
    public interface IUserRepo
    {
        string GetName(int id);
    }

    public class UserService
    {
        private readonly IUserRepo _repo;
        public UserService(IUserRepo repo) => _repo = repo;

        public string Greet(int id) => $"Hello, {_repo.GetName(id)}!";
    }
}

3.添加单元测试

项目模板选择 xUnit测试项目
MlyMathLibTests
注意检查coverlet.collector 和Moq的库引用

4.编写测试用例

using MlyMathLib;
using Moq;

namespace MlyMathLibTests
{
    public class UserServiceTests
    {
        private readonly Mock<IUserRepo> _repoMock = new();
        private readonly UserService _sut;

        public UserServiceTests()
        {
            _sut = new UserService(_repoMock.Object);
        }

        #region Greet

        [Fact]
        public void Greet_IdExists_ReturnsExpectedGreeting()
        {
            // Arrange
            _repoMock.Setup(r => r.GetName(1)).Returns("Alice");

            // Act
            var actual = _sut.Greet(1);

            // Assert
            Assert.Equal("Hello, Alice!", actual);
            _repoMock.Verify(r => r.GetName(1), Times.Once);
        }

        [Theory]
        [InlineData(0, "")]
        [InlineData(-1, "Bob")]
        [InlineData(int.MaxValue, "Z")]
        public void Greet_VariousValidIds_ReturnsCorrectGreeting(int id, string name)
        {
            // Arrange
            _repoMock.Setup(r => r.GetName(id)).Returns(name);

            // Act & Assert
            Assert.Equal($"Hello, {name}!", _sut.Greet(id));
        }

        [Fact]
        public void Greet_RepoReturnsNull_ReturnsHelloNull()
        {
            // Arrange
            _repoMock.Setup(r => r.GetName(42)).Returns((string?)null);

            // Act
            var actual = _sut.Greet(42);

            // Assert
            Assert.Equal("Hello, !", actual); // 实际输出:Hello, !
        }

        #endregion
    }
}

5.运行项目

如果没报错,终端会出现控制台和输出内容

6.生成报告(覆盖率)

打开终端
依次运行命令
注意:路径和反斜杠问题

# 1. 运行测试并收集覆盖率(生成 cobertura 格式的 xml)
dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults

# 2. 安装 ReportGenerator(全局只需一次)
dotnet tool install -g dotnet-reportgenerator-globaltool

# 3. 把 xml 转成漂亮的 HTML
reportgenerator \
  -reports:"TestResults/*/coverage.cobertura.xml" \
  -targetdir:"coverage-html" \
  -reporttypes:"Html;Cobertura" \
  -title:"DemoLib 单元测试报告"

# 4. 打开报告(Windows 用 start,macOS 用 open,Linux 用 xdg-open)
start coverage-html/index.html        # Windows
# open coverage-html/index.html       # macOS
# xdg-open coverage-html/index.html   # Linux

实际命令

dotnet test --collect:"XPlat Code Coverage"
dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults
dotnet tool install -g dotnet-reportgenerator-globaltool

reportgenerator -reports:"TestResults\60fe6df2-8246-45b8-81ef-cd4d267aa97c\coverage.cobertura.xml" -targetdir:"coverage-html" -reporttypes:"Html;Cobertura" -title:"DemoLib"

reportgenerator -reports:“TestResults\89f052dd-c413-470d-be24-832e2d53251e\coverage.cobertura.xml” -targetdir:“coverage-html” -reporttypes:“Html;Cobertura” -title:“Common.Logger.Tests”

7.生成报告(是否通过)

使用 dotnet test 生成测试报告
运行以下命令,生成测试报告:

dotnet test --logger "trx;LogFileName=test-results.trx"

这会在当前目录下生成一个 test-results.trx 文件,该文件是一个 XML 格式的测试报告,包含了每个测试的通过/失败情况。

extentreports-dotnet-cli

Trxer

Usage
Trxer is an EXE file.
Trxer.exe <file.trx>
The output will be at the trx folder under the name “file.trx.html”

TrxerConsole.exe <TRX file>

下载项目 重新编译
https://github.com/NivNavick/trxer


网站公告

今日签到

点亮在社区的每一天
去签到