单元测试 运行 永远用于 C# 中的回调方法
Unit test running forever for call back method in C#
以下是RabbitMq Queue接收消息的方法。方法工作正常,但是单元测试这个方法有下面提到的问题
public void GetMessage(Action<string> action)
{
//create a connection factory
var factory = new ConnectionFactory();
if (_connectionString != null)
{
//assign connection string of rabbitmq
factory.Uri = new Uri(_connectionString);
}
//create connection and channel from connectionfactory
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
//declare the queque on the channel
channel.QueueDeclare(queue: _queque,
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
//create consumer using the channel
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
//When message is recieved on the consumer this will be triggered
var body = ea.Body.ToArray();
_message = Encoding.UTF8.GetString(body);
//call the method passed by the caller method
action(_message);
};
//add the consumer on this channel
channel.BasicConsume(queue: _queque,
autoAck: true,
consumer: consumer);
Console.ReadLine();
}
}
如何编写单元测试测试上面的消息。下面的单元测试在回调方法中永远加载并且执行永远不会进入 Assert.Equal 行。
[Fact]
public async Task AddMessageAsync_ShouldAddToQueue()
{
//Arrange
string messageToSend = "Test";
string recievedMessage = null;
var queue = GetQueueManager();
queue.Message = messageToSend;
await queue.AddMessageAsync();
//Act
queue.GetMessage((string message) =>
{
//Hit here and recieved the message but does not exist from this method
recievedMessage = message;
});
//Assert
Assert.Equal(messageToSend, recievedMessage);
}
解决该问题的一种方法是同步障碍。
这是一个示例:(不过,可能还有更有效的方法。)
... // Your code with some changes:
//create connection and channel from connectionfactory
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
//declare the queque on the channel
channel.QueueDeclare(queue: _queque,
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
// Set up a synchronization barrier.
using (var barrier = new ManualResetEventSlim(false))
{
//create consumer using the channel
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
//When message is recieved on the consumer this will be triggered
var body = ea.Body.ToArray();
_message = Encoding.UTF8.GetString(body);
try // you don't want "injected" code to break yours.
{
//call the method passed by the caller method
action(_message);
}
catch(Exception)
{
// at least log it!
}
finally
{
barrier.Set(); // Signal Event fired.
}
};
//add the consumer on this channel
channel.BasicConsume(queue: _queque,
autoAck: true,
consumer: consumer);
barrier.Wait(); // Wait for Event to fire.
}
}
我想 RabbitMQ API 有一个更新来支持 async/await 而不是 event-based?如果是这样,那么使用它当然是更可取的。
如果没有:您可能还想探索 Tasks and the Event-based Asynchronous Pattern (EAP)
以下是RabbitMq Queue接收消息的方法。方法工作正常,但是单元测试这个方法有下面提到的问题
public void GetMessage(Action<string> action)
{
//create a connection factory
var factory = new ConnectionFactory();
if (_connectionString != null)
{
//assign connection string of rabbitmq
factory.Uri = new Uri(_connectionString);
}
//create connection and channel from connectionfactory
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
//declare the queque on the channel
channel.QueueDeclare(queue: _queque,
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
//create consumer using the channel
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
//When message is recieved on the consumer this will be triggered
var body = ea.Body.ToArray();
_message = Encoding.UTF8.GetString(body);
//call the method passed by the caller method
action(_message);
};
//add the consumer on this channel
channel.BasicConsume(queue: _queque,
autoAck: true,
consumer: consumer);
Console.ReadLine();
}
}
如何编写单元测试测试上面的消息。下面的单元测试在回调方法中永远加载并且执行永远不会进入 Assert.Equal 行。
[Fact]
public async Task AddMessageAsync_ShouldAddToQueue()
{
//Arrange
string messageToSend = "Test";
string recievedMessage = null;
var queue = GetQueueManager();
queue.Message = messageToSend;
await queue.AddMessageAsync();
//Act
queue.GetMessage((string message) =>
{
//Hit here and recieved the message but does not exist from this method
recievedMessage = message;
});
//Assert
Assert.Equal(messageToSend, recievedMessage);
}
解决该问题的一种方法是同步障碍。 这是一个示例:(不过,可能还有更有效的方法。)
... // Your code with some changes:
//create connection and channel from connectionfactory
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
//declare the queque on the channel
channel.QueueDeclare(queue: _queque,
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
// Set up a synchronization barrier.
using (var barrier = new ManualResetEventSlim(false))
{
//create consumer using the channel
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
//When message is recieved on the consumer this will be triggered
var body = ea.Body.ToArray();
_message = Encoding.UTF8.GetString(body);
try // you don't want "injected" code to break yours.
{
//call the method passed by the caller method
action(_message);
}
catch(Exception)
{
// at least log it!
}
finally
{
barrier.Set(); // Signal Event fired.
}
};
//add the consumer on this channel
channel.BasicConsume(queue: _queque,
autoAck: true,
consumer: consumer);
barrier.Wait(); // Wait for Event to fire.
}
}
我想 RabbitMQ API 有一个更新来支持 async/await 而不是 event-based?如果是这样,那么使用它当然是更可取的。
如果没有:您可能还想探索 Tasks and the Event-based Asynchronous Pattern (EAP)