Moq 触发 Func<T1, Task> 的事件

huangapple go评论66阅读模式
英文:

Moq Raise event of Func<T1, Task>

问题

我有一个第三方类MqttClient,它内部有一个事件(Func<T1, Task>)。我想在MyClient类内监听此事件,并在事件被触发时更新我的类内的IsConnected属性。为了进行测试,我已经模拟了IMqttClient接口,并希望引发该事件,以便在发生时测试我的属性是否得到更新。然而,当我尝试这样做时,出现了关于参数计数不匹配的错误。

以下是我尝试的测试:

[Fact]
public void Connect_IsConnectedSetToTrue()
{
    MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x => x.ConnectedAsync += null);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}
[Fact]
public void Connect_IsConnectedSetToTrue()
{
    MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x => x.ConnectedAsync += null, eventArgs);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}
[Fact]
public void Connect_IsConnectedSetToTrue()
{
    MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x => x.ConnectedAsync += null, this, eventArgs);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}

MyClient类如下:

public class MyClient
{
    private readonly IMqttClient _client;

    public bool IsConnected { get; private set; } = false;

    public MQTTClient(IMQTTNetClientFactory mqttNetFactory)
    {
        _client = mqttNetFactory.Create();
        _client.ConnectedAsync += Client_ConnectedAsync;
    }

    public async Task Connect()
    {
        MqttClientOptions options = new MqttClientOptionsBuilder()
            .WithTcpServer(_url, _port)
            .WithCredentials(_username, _password)
            .WithProtocolVersion(MqttProtocolVersion.V500)
            .Build();

        await _client.ConnectAsync(options);
    }

    private Task Client_ConnectedAsync(MqttClientConnectedEventArgs arg)
    {
        _logger.LogInformation("Client connected to the MQTT broker.");
        IsConnected = true;
        return Task.FromResult(0);
    }
}

MqttClient类内的事件如下:

public interface IMqttClient : IDisposable
{
    event Func<MqttClientConnectedEventArgs, Task> ConnectedAsync;
}

希望这些信息对你有所帮助,如果你需要更多的解释或帮助,请随时提出。

英文:

I have a third-party class MqttClient which has an event inside it (Func&lt;T1, Task&gt;). I want to listen for this event inside the MyClient class and when it gets invoked, I update the property IsConnected inside my class. For my tests, I have mocked the IMqttClient interface, and I want to raise that event so that I can test that my property gets updated when it happens. However, when I try to do this I get an error about parameter count mismatches. I've found a lot of examples about using EventHandler&lt;T&gt; but since this class is outside of my control, I need it to work with a Func.

> System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'

Here are the tests I've tried:

[Fact]
public void Connect_IsConnectedSetToTrue()
{
    MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x =&gt; x.ConnectedAsync += null);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}

[Fact]
public void Connect_IsConnectedSetToTrue()
{
     MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x =&gt; x.ConnectedAsync += null, eventArgs);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}

[Fact]
public void Connect_IsConnectedSetToTrue()
{
    MqttClientConnectedEventArgs eventArgs = new(new MqttClientConnectResult());
    _mockMqttNetClient.Raise(x =&gt; x.ConnectedAsync += null, this, eventArgs);
    _mqttClient.Connect();
    Assert.True(_mqttClient.IsConnected);
}

The MyClient class:

public class MyClient
{
    private readonly IMqttClient _client;

    public bool IsConnected { get; private set; } = false;

    public MQTTClient(IMQTTNetClientFactory mqttNetFactory)
    {
        _client = mqttNetFactory.Create();
        _client.ConnectedAsync += Client_ConnectedAsync;
    }

    public async Task Connect()
    {
        MqttClientOptions options = new MqttClientOptionsBuilder()
            .WithTcpServer(_url, _port)
            .WithCredentials(_username, _password)
            .WithProtocolVersion(MqttProtocolVersion.V500)
            .Build();

        await _client.ConnectAsync(options);
    }

   
    private Task Client_ConnectedAsync(MqttClientConnectedEventArgs arg)
    {
        _logger.LogInformation(&quot;Client connected to the MQTT broker.&quot;);
        IsConnected = true;
        return Task.FromResult(0);
    }
}

This is what the event looks like inside the MqttClient class.

public interface IMqttClient : IDisposable
{
    event Func&lt;MqttClientConnectedEventArgs, Task&gt; ConnectedAsync;
}

Thanks,
Adam

答案1

得分: 2

按照 @Ralf 所说:

> 你使用的 raise 重载期望它是一个事件处理程序(发送方+参数的东西),但只提供了一个参数类,并将发送方搞进了调用中

以这种方式解决了我的问题。

_mockMqttNetClient.Raise(x => x.DisconnectedAsync += null, new object[] { eventArgs });
英文:

As @Ralf said

> The raise overload you use expects that it is an Eventhandler(the sender+args thingy) when only given an args class and fiddles a sender into the call

Doing it this way solved my issue.

_mockMqttNetClient.Raise(x =&gt; x.DisconnectedAsync += null, new object[] { eventArgs });

huangapple
  • 本文由 发表于 2023年4月4日 17:37:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75927809.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定