PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/EasyNetQ.Tests/ProducerTests/PublisherConfirmsTests.cs

http://github.com/mikehadlow/EasyNetQ
C# | 413 lines | 318 code | 84 blank | 11 comment | 1 complexity | 2dc5786a1c1981bbd170279e6519de7b MD5 | raw file
Possible License(s): Apache-2.0
  1. // ReSharper disable InconsistentNaming
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Threading.Tasks;
  5. using EasyNetQ.Events;
  6. using EasyNetQ.Producer;
  7. using NUnit.Framework;
  8. using RabbitMQ.Client;
  9. using RabbitMQ.Client.Events;
  10. using RabbitMQ.Client.Framing;
  11. using Rhino.Mocks;
  12. namespace EasyNetQ.Tests.ProducerTests
  13. {
  14. [TestFixture]
  15. public class PublisherBasicTests
  16. {
  17. private IPublisher publisher;
  18. private IEventBus eventBus;
  19. IModel channel;
  20. [SetUp]
  21. public void SetUp()
  22. {
  23. channel = MockRepository.GenerateStub<IModel>();
  24. eventBus = MockRepository.GenerateStub<IEventBus>();
  25. publisher = new PublisherBasic(eventBus);
  26. }
  27. [Test]
  28. public void Should_register_for_message_returns()
  29. {
  30. publisher.Publish(channel, model => { }).Wait();
  31. channel.AssertWasCalled(x => x.BasicReturn += Arg<BasicReturnEventHandler>.Is.Anything);
  32. }
  33. [Test]
  34. public void Should_complete_task_immediately_without_waiting_for_ack()
  35. {
  36. var taskWasExecuted = false;
  37. var task = publisher.Publish(channel, model => taskWasExecuted = true);
  38. task.Wait();
  39. taskWasExecuted.ShouldBeTrue();
  40. }
  41. }
  42. [TestFixture]
  43. public class PublisherBasicTests_when_message_returned
  44. {
  45. private IPublisher publisher;
  46. private IEventBus eventBus;
  47. private IModel channelMock;
  48. [SetUp]
  49. public void SetUp()
  50. {
  51. channelMock = MockRepository.GenerateStub<IModel>();
  52. eventBus = MockRepository.GenerateStub<IEventBus>();
  53. publisher = new PublisherBasic(eventBus);
  54. }
  55. [Test]
  56. public void Should_raise_message_returned_event_when_message_returned()
  57. {
  58. const string exchange = "the exchange";
  59. const string replyText = "reply text";
  60. const string routingKey = "routing key";
  61. var body = new byte[0];
  62. var properties = new BasicProperties();
  63. publisher.Publish(channelMock, model => { }).Wait();
  64. channelMock.Raise(x => x.BasicReturn += null, null, new BasicReturnEventArgs
  65. {
  66. Body = body,
  67. Exchange = exchange,
  68. ReplyText = replyText,
  69. RoutingKey = routingKey,
  70. BasicProperties = properties
  71. });
  72. var arg = eventBus.GetArgumentsForCallsMadeOn(x => x.Publish(Arg<ReturnedMessageEvent>.Is.Anything))[0][0];
  73. var messageEvent = arg as ReturnedMessageEvent;
  74. Assert.NotNull(messageEvent);
  75. Assert.AreSame(body, messageEvent.Body);
  76. Assert.NotNull(messageEvent.Properties);
  77. Assert.AreEqual(exchange, messageEvent.Info.Exchange);
  78. Assert.AreEqual(replyText, messageEvent.Info.ReturnReason);
  79. Assert.AreEqual(routingKey, messageEvent.Info.RoutingKey);
  80. }
  81. }
  82. [TestFixture]
  83. public class PublisherBasicTests_when_channel_reconnects
  84. {
  85. private IPublisher publisher;
  86. private IEventBus eventBus;
  87. [SetUp]
  88. public void SetUp()
  89. {
  90. eventBus = new EventBus();
  91. publisher = new PublisherBasic(eventBus);
  92. }
  93. [Test]
  94. public void Should_remove_event_handler_from_old_channel()
  95. {
  96. var channel1 = MockRepository.GenerateStub<IModel>();
  97. var channel2 = MockRepository.GenerateStub<IModel>();
  98. publisher.Publish(channel1, model => { }).Wait();
  99. eventBus.Publish(new PublishChannelCreatedEvent(channel2));
  100. publisher.Publish(channel2, model => { }).Wait();
  101. channel1.AssertWasCalled(x => x.BasicReturn -= Arg<BasicReturnEventHandler>.Is.Anything);
  102. }
  103. }
  104. [TestFixture]
  105. public class PublisherFactoryTests_when_publisher_confirms_enabled
  106. {
  107. private IPublisher publisher;
  108. [Test]
  109. public void Should_return_instance_of_publisher_confirms()
  110. {
  111. var eventBus = MockRepository.GenerateStub<IEventBus>();
  112. var logger = MockRepository.GenerateStub<IEasyNetQLogger>();
  113. var connectionConfiguration = new ConnectionConfiguration
  114. {
  115. PublisherConfirms = true
  116. };
  117. publisher = PublisherFactory.CreatePublisher(connectionConfiguration, logger, eventBus);
  118. Assert.IsAssignableFrom<PublisherConfirms>(publisher);
  119. }
  120. }
  121. [TestFixture]
  122. public class PublisherFactoryTests_when_publisher_confirms_disabled
  123. {
  124. private IPublisher publisher;
  125. [Test]
  126. public void Should_return_instance_of_publisher_basic()
  127. {
  128. var eventBus = MockRepository.GenerateStub<IEventBus>();
  129. var logger = MockRepository.GenerateStub<IEasyNetQLogger>();
  130. var connectionConfiguration = new ConnectionConfiguration
  131. {
  132. PublisherConfirms = false
  133. };
  134. publisher = PublisherFactory.CreatePublisher(connectionConfiguration, logger, eventBus);
  135. Assert.IsAssignableFrom<PublisherBasic>(publisher);
  136. }
  137. }
  138. [TestFixture]
  139. public class PublisherConfirmsTests
  140. {
  141. private IPublisher publisherConfirms;
  142. IModel channel;
  143. private IEventBus eventBus;
  144. [SetUp]
  145. public void SetUp()
  146. {
  147. channel = MockRepository.GenerateStub<IModel>();
  148. eventBus = MockRepository.GenerateStub<IEventBus>();
  149. var connectionConfiguration = new ConnectionConfiguration
  150. {
  151. Timeout = 1
  152. };
  153. var logger = MockRepository.GenerateStub<IEasyNetQLogger>();
  154. publisherConfirms = new PublisherConfirms(connectionConfiguration, logger, eventBus);
  155. }
  156. [Test]
  157. public void Should_register_for_message_returns()
  158. {
  159. var task = publisherConfirms.Publish(channel, model => { });
  160. channel.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  161. task.Wait();
  162. channel.AssertWasCalled(x => x.BasicReturn += Arg<BasicReturnEventHandler>.Is.Anything);
  163. }
  164. [Test]
  165. public void Should_register_for_publisher_confirms()
  166. {
  167. var task = publisherConfirms.Publish(channel, model => { });
  168. channel.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  169. task.Wait();
  170. channel.AssertWasCalled(x => x.ConfirmSelect());
  171. }
  172. [Test]
  173. public void Should_complete_successfully_when_acked()
  174. {
  175. var actionWasExecuted = false;
  176. var task = publisherConfirms.Publish(channel, model => actionWasExecuted = true);
  177. channel.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  178. task.Wait();
  179. actionWasExecuted.ShouldBeTrue();
  180. }
  181. [Test]
  182. [ExpectedException(typeof(PublishNackedException))]
  183. public void Should_throw_exception_when_nacked()
  184. {
  185. var task = publisherConfirms.Publish(channel, model => {});
  186. channel.Raise(x => x.BasicNacks += null, null, new BasicNackEventArgs());
  187. try
  188. {
  189. task.Wait();
  190. }
  191. catch (AggregateException aggregateException)
  192. {
  193. throw aggregateException.InnerException;
  194. }
  195. }
  196. [Test]
  197. [ExpectedException(typeof(TimeoutException))]
  198. public void Should_timeout_if_neither_ack_or_nack_is_raised()
  199. {
  200. var task = publisherConfirms.Publish(channel, model => { });
  201. try
  202. {
  203. task.Wait();
  204. }
  205. catch (AggregateException aggregateException)
  206. {
  207. throw aggregateException.InnerException;
  208. }
  209. }
  210. [Test]
  211. public void Should_match_ack_with_sequence_number()
  212. {
  213. ulong sequenceNumber = 0;
  214. channel.Stub(x => x.NextPublishSeqNo).WhenCalled(x => x.ReturnValue = sequenceNumber++).Return(0);
  215. var tasks = new List<Task>();
  216. for (ulong i = 0; i < 10; i++)
  217. {
  218. tasks.Add(publisherConfirms.Publish(channel, model => { }));
  219. channel.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs
  220. {
  221. DeliveryTag = i
  222. });
  223. }
  224. Task.WaitAll(tasks.ToArray());
  225. }
  226. }
  227. [TestFixture]
  228. public class PublisherConfirmsTests_when_message_returned
  229. {
  230. private IPublisher publisherConfirms;
  231. private IEventBus eventBus;
  232. private IModel channel;
  233. [SetUp]
  234. public void SetUp()
  235. {
  236. channel = MockRepository.GenerateStub<IModel>();
  237. eventBus = MockRepository.GenerateStub<IEventBus>();
  238. var connectionConfiguration = new ConnectionConfiguration
  239. {
  240. Timeout = 1
  241. };
  242. var logger = MockRepository.GenerateStub<IEasyNetQLogger>();
  243. publisherConfirms = new PublisherConfirms(connectionConfiguration, logger, eventBus);
  244. }
  245. [Test]
  246. public void Should_raise_message_returned_event_when_message_returned()
  247. {
  248. const string exchange = "the exchange";
  249. const string replyText = "reply text";
  250. const string routingKey = "routing key";
  251. var body = new byte[0];
  252. var properties = new BasicProperties();
  253. var task = publisherConfirms.Publish(channel, model => { });
  254. channel.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  255. channel.Raise(x => x.BasicReturn += null, null, new BasicReturnEventArgs
  256. {
  257. Body = body,
  258. Exchange = exchange,
  259. ReplyText = replyText,
  260. RoutingKey = routingKey,
  261. BasicProperties = properties
  262. });
  263. task.Wait();
  264. var arg = eventBus.GetArgumentsForCallsMadeOn(x => x.Publish(Arg<ReturnedMessageEvent>.Is.Anything))[0][0];
  265. var messageEvent = arg as ReturnedMessageEvent;
  266. Assert.NotNull(messageEvent);
  267. Assert.AreSame(body, messageEvent.Body);
  268. Assert.NotNull(messageEvent.Properties);
  269. Assert.AreEqual(exchange, messageEvent.Info.Exchange);
  270. Assert.AreEqual(replyText, messageEvent.Info.ReturnReason);
  271. Assert.AreEqual(routingKey, messageEvent.Info.RoutingKey);
  272. }
  273. }
  274. [TestFixture]
  275. public class PublisherConfirmsTests_when_channel_reconnects
  276. {
  277. private IPublisher publisherConfirms;
  278. private IEventBus eventBus;
  279. [SetUp]
  280. public void SetUp()
  281. {
  282. eventBus = new EventBus();
  283. var connectionConfiguration = new ConnectionConfiguration
  284. {
  285. PublisherConfirms = true,
  286. Timeout = 1000
  287. };
  288. var logger = MockRepository.GenerateStub<IEasyNetQLogger>();
  289. publisherConfirms = PublisherFactory.CreatePublisher(connectionConfiguration, logger, eventBus);
  290. }
  291. [Test]
  292. public void Should_complete_task_when_new_model_acks()
  293. {
  294. var channel1 = MockRepository.GenerateStub<IModel>();
  295. var channel2 = MockRepository.GenerateStub<IModel>();
  296. var modelsUsedInPublish = new List<IModel>();
  297. // do the publish, this should be retried against the new model after it reconnects.
  298. var task = publisherConfirms.Publish(channel1, modelsUsedInPublish.Add);
  299. // new channel connects
  300. eventBus.Publish(new PublishChannelCreatedEvent(channel2));
  301. // new channel ACKs (sequence number is 0)
  302. channel2.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  303. // wait for task to complete
  304. task.Wait();
  305. // should have published on both channels:
  306. modelsUsedInPublish.Count.ShouldEqual(2);
  307. modelsUsedInPublish[0].ShouldBeTheSameAs(channel1);
  308. modelsUsedInPublish[1].ShouldBeTheSameAs(channel2);
  309. }
  310. [Test]
  311. public void Should_remove_event_handler_from_old_channel()
  312. {
  313. var channel1 = MockRepository.GenerateStub<IModel>();
  314. var channel2 = MockRepository.GenerateStub<IModel>();
  315. // do the publish, this should be retried against the new model after it reconnects.
  316. var task = publisherConfirms.Publish(channel1, model => { });
  317. // new channel connects
  318. eventBus.Publish(new PublishChannelCreatedEvent(channel2));
  319. // new channel ACKs (sequence number is 0)
  320. channel2.Raise(x => x.BasicAcks += null, null, new BasicAckEventArgs());
  321. // wait for task to complete
  322. task.Wait();
  323. channel1.AssertWasCalled(x => x.BasicAcks -= Arg<BasicAckEventHandler>.Is.Anything);
  324. channel1.AssertWasCalled(x => x.BasicNacks -= Arg<BasicNackEventHandler>.Is.Anything);
  325. channel1.AssertWasCalled(x => x.BasicReturn -= Arg<BasicReturnEventHandler>.Is.Anything);
  326. }
  327. }
  328. }
  329. // ReSharper restore InconsistentNaming