英文:
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<T1, Task>). 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<T> 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 => 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);
}
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("Client connected to the MQTT broker.");
        IsConnected = true;
        return Task.FromResult(0);
    }
}
This is what the event looks like inside the MqttClient class.
public interface IMqttClient : IDisposable
{
    event Func<MqttClientConnectedEventArgs, Task> 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 => x.DisconnectedAsync += null, new object[] { eventArgs });
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论