我尝试对一个相当基本的场景进行单元测试 - 具有2个工作者和1个发布者场景的工作队列,但它不断地从队列中一遍又一遍地返回相同的消息。
测试中的以下代码只会将1到100条消息放入队列,而2位消费者会将它们消耗掉。问题是他们只是收到消息1和2.我试图将确认分成一个方法,因为在我的应用程序中,消息需要时间来获取进程(评论方法确认) - 然后它抛出了令牌未知的异常:
AMQP操作被中断:AMQP关闭原因,由...发起 同行,代码= 406,文本=" PRECONDITION_FAILED - 未知交货标签1", classId = 60,methodId = 80,cause =
似乎承认在某种程度上被打破了。我试图把它关掉 - 没有运气。
类:
using System;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
namespace Backend.MQ.OCR
{
public class BatchQueue : QueueBase<BatchMessage>
{
private readonly IModel _channel;
private const string QPrefix = "ocrbatches_";
private readonly QueueingBasicConsumer _consumer;
private ulong _latesttoken = ulong.MaxValue;
private readonly string _jobid;
public BatchQueue(string connectionString, String jobid):
base(connectionString)
{
_jobid = jobid;
var factory = new ConnectionFactory()
{
HostName = connectionString
};
var connection = factory.CreateConnection();
_channel = connection.CreateModel();
_channel.QueueDeclare(Name, true, false, false, null);
//binding consumers
_channel.BasicQos(0, 1, false);
_consumer = new QueueingBasicConsumer(_channel);
_channel.BasicConsume(Name, false, _consumer);
}
public override void Publish(BatchMessage msg)
{
var message = JsonConvert.SerializeObject(msg);
var body = Encoding.UTF8.GetBytes(message);
var properties = _channel.CreateBasicProperties();
properties.SetPersistent(true);
_channel.BasicPublish("", Name, properties, body);
#if DEBUG
System.Diagnostics.Trace.WriteLine("[x] Sent task:" + msg);
#endif
}
private string Name
{
get { return QPrefix + _jobid; }
}
public override BatchMessage Receive()
{
var ea =
(BasicDeliverEventArgs)_consumer.Queue.Dequeue();
var body = ea.Body;
_channel.BasicAck(ea.DeliveryTag, false);
return JsonConvert.DeserializeObject<BatchMessage>(Encoding.UTF8.GetString(body));
}
public override void Confirm()
{
//if (_latesttoken < ulong.MaxValue) _channel.BasicAck(_latesttoken, false);
}
}
}
单元测试:
#if NUNIT
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute;
using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute;
#else
#endif
using System.Threading.Tasks;
using System.Threading;
using System;
using System.Collections.Generic;
using Backend.MQ.OCR;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#if NUNIT
using MAssert = NUnit.Framework.Assert;
#else
using MAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
#endif
namespace MQ.Test
{
[TestClass]
public class BatchQueueTest
{
[TestMethod]
public void Concurrencytest()
{
var batchname = Guid.NewGuid().ToString();
var queue = new BatchQueue("localhost", batchname);
var tasks = new List<Task>();
var counter = 0;
for (int i = 0; i < 100; i++)
{
queue.Publish(new BatchMessage()
{
Files = new List<string>() { i.ToString() }
});
}
for (int i = 0; i < 2; i++)
{
var task = Task.Factory.StartNew(() =>
{
var q = new BatchQueue("localhost", batchname);
var res = q.Receive();
while (res != null)
{
System.Diagnostics.Trace.WriteLine(res.Files[0]);
q.Confirm();
Interlocked.Increment(ref counter);
}
});
tasks.Add(task);
}
var ok = Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));
MAssert.IsTrue(ok, "Tasks didnt complete in time");
MAssert.AreEqual(counter, 100, "Not all messages have been processed");
}
}
}
答案 0 :(得分:2)
您的单元测试启动两项任务。在while循环之前,您会收到一条消息,但是您仍然在while循环中确认相同的消息:
var res = q.Receive();
尝试将<ul>
<li value="{name:34}">Item Two</li>
</ul>
放入循环