﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DisposeShould.cs" company="Epworth Consulting Ltd.">
//   © Epworth Consulting Ltd.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Atlas.ServiceBus.RabbitMQ.Tests.RabbitMQServiceBusTests
{
   using System;

   using Atlas.ServiceBus.RabbitMQ.Implementations;
   using Atlas.ServiceBus.Testing.MessageHandlers;

   using FakeItEasy;

   using NUnit.Framework;

   public class DisposeShould : RabbitMQServiceBusTestsBase
   {      
      private IMessageSubscription messageSubscription;

      private RabbitMQServiceBus componentUnderTest;

      [SetUp]
      public void SetupBeforeEachTest()
      {         
         this.messageSubscription = A.Fake<IMessageSubscription>();

         A.CallTo(() => this.MessageSubscriptionFactory.Create(A<IChannelManagerFactory>._, A<Type[]>._)).Returns(this.messageSubscription);

         this.componentUnderTest = this.CreateRabbitMQServiceBus();
      }

      [Test]
      public void DisposeOfChannelManager()
      {
         this.componentUnderTest.Dispose();

         A.CallTo(() => this.ChannelManager.Dispose()).MustHaveHappened(Repeated.Exactly.Once);
      }

      [Test]
      public void DisposeOfChannelManagerOnlyOnce()
      {
         this.componentUnderTest.Dispose();
         this.componentUnderTest.Dispose();

         A.CallTo(() => this.ChannelManager.Dispose()).MustHaveHappened(Repeated.Exactly.Once);
      }

      [Test]
      public void ShouldNotDisposeOfChannelManagerDuringFinalise()
      {
         this.componentUnderTest = null;
         GC.Collect();
         GC.WaitForPendingFinalizers();

         A.CallTo(() => this.ChannelManager.Dispose()).MustNotHaveHappened();
      }

      [Test]
      public void DisposeSubscription()
      {
         this.componentUnderTest.Receive(typeof(TestMessageAHandler));

         this.componentUnderTest.Dispose();

         A.CallTo(() => this.messageSubscription.Dispose()).MustHaveHappened(Repeated.Exactly.Once);
      }

      [Test]
      public void DisposeSubscriptionOnlyOnce()
      {
         this.componentUnderTest.Receive(typeof(TestMessageAHandler));

         this.componentUnderTest.Dispose();
         this.componentUnderTest.Dispose();

         A.CallTo(() => this.messageSubscription.Dispose()).MustHaveHappened(Repeated.Exactly.Once);
      }

      [Test]
      public void ShouldNotDisposeSubscriptionDuringFinalise()
      {
         this.componentUnderTest.Receive(typeof(TestMessageAHandler));

         this.componentUnderTest = null;
         GC.Collect();
         GC.WaitForPendingFinalizers();

         A.CallTo(() => this.messageSubscription.Dispose()).MustNotHaveHappened();
      }
   }
}
