c# - 如何注入(inject)一个不提供接口(interface)和虚拟方法的类的伪实现?

标签 c# moq xunit discord.net

我正在使用为我提供 DiscordSocketClient 的 Discord.Net 软件包类,目前在我的 DI 容器中是一个 Singleton。我需要实例中的几种方法

  • Task LoginAsync(TokenType tokenType, string token, bool validateToken = true)
  • Task StartAsync()
  • Task LogoutAsync()
  • Task StopAsync()

给定这个使用方法的示例类

public sealed class ConsumingClass
{
    private readonly DiscordSocketClient _discordSocketClient;
    
    public ConsumingClass(DiscordSocketClient discordSocketClient)
    {
        _discordSocketClient = discordSocketClient;
    }
    
    public override async Task Initialize(CancellationToken cancellationToken)
    {
        await _discordSocketClient.LoginAsync(TokenType.Bot, "my-token");
        await _discordSocketClient.StartAsync();
    }
    
    public override async Task TearDown(CancellationToken cancellationToken)
    {
        await _discordSocketClient.LogoutAsync();
        await _discordSocketClient.StopAsync();
    }
}

我想使用 XUnit 和 Moq 创建测试以确保 ConsumingClass 的实例按预期工作。

不幸的是DiscordSocketClient不提供接口(interface),因此我无法将模拟实现注入(inject)到我的测试中。

此外,这些方法不是虚拟的,因此无法创建 Mock<DiscordSocketClient> 的实例并使用 .Setup()设置模拟实现。

那么我如何在我的测试用例中验证客户端方法是否已被调用一次?例如。 _discordSocketClientMock.Verify(discordSocketClient => discordSocketClient.LoginAsync(), Times.Once());

我必须创建一个接口(interface)吗 IMyDiscordSocketClient提供这些方法和一个类另一个类MyDiscordSocketClient继承自 DiscordSocketClient并实现接口(interface)并使用它?或者有什么更好的方法吗?

最佳答案

如果 DiscordSocketClient 没有(公共(public))虚拟成员,您也不能真正从它派生。然而,您的最后一个建议可能仍然是您拥有的最佳可能性,除了 MyDiscordSocketClient 不应派生自 DiscordSocketClient,而是聚合一个。


public class MyDiscordSocketClient: IMyDiscordSocketClient
{
    private DiscordSocketClient _client;
    public MyDiscordSocketClient(DiscordSocketClient client)
    {
        _client = _client;
    }
    
    public async Task Initialize(CancellationToken cancellationToken)
    {
         _client.Initialize(cancellationToken);
    }

    // etc...
}

关于c# - 如何注入(inject)一个不提供接口(interface)和虚拟方法的类的伪实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70134407/

相关文章:

c# - 使用 Moq 和 xUnit 对服务进行单元测试

c# - 模拟 ApiController SignalR 广播

c# - 如何使任务失败然后断言异常

c# - 错误 : This template attempted to load component assembly 'Microsoft.VisualStudio.SmartDevice'

c# - C# 托管代码中的 "AccessViolationException was unhandled"错误

c# - 类似 DateTimePicker 的输入控件

ninject - 在集成测试中使用 IMapper

c# - 使用 C# .NET 处理 XML 中的禁用字符

c# - 测试工厂模式

c# - 您如何测试是否已创建对象的新实例?