public void BusResponseSolutionContainsNullSolutionAndNoErrors_ExceptionIsRaised()
        {
            var key = _orgA1;

            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution,
                                        It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse());

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            try
            {
                sut.GetValue(key);
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidOperationException ex)
            {
                Assert.IsTrue(ex.Message.Equals("Bus response contained no solution. Most likely no response was received in time.", StringComparison.OrdinalIgnoreCase));
            }

            _loggerMock.Verify(x => x.Error("OrganisationHierarchyCache.GetOrganisationTreeItemForOrganisation",
                                            It.Is <LogItem[]>(li =>
                                                              li[0].Key.Equals("Event") &&
                                                              li[0].Value.Invoke().Equals("Bus response contained no solution. Most likely no response was received in time.") &&
                                                              li[1].Key.Equals("organisationId") &&
                                                              li[1].Value.Invoke().Equals(_orgA1.ToString())
                                                              )));

            _backplaneMock.VerifyNoOtherCalls();
        }
        public void GetValue_WithValidKeyAlreadyInCache_ButCacheTimeSetToZero_MessageIsPublishedTwice()
        {
            _configurationManagerMock.Setup(x => x.Get("OrganisationCacheTimeout", It.IsAny <int>())).Returns(0);//cache time of zero.

            var key = _orgA1;

            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution, It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse {
                Solution = JsonConvert.SerializeObject(_relationshipSampleData)
            });

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            var resultFromPublishingMessage = sut.GetValue(key);
            var resultFromCachedItem        = sut.GetValue(key);

            Assert.IsNotNull(resultFromPublishingMessage);
            Assert.IsTrue(ResultDataTreeIsCorrect(resultFromPublishingMessage));

            Assert.IsNotNull(resultFromCachedItem);
            Assert.IsTrue(ResultDataTreeIsCorrect(resultFromCachedItem));

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <object, Relationship> >(m =>
                                                                                 m.Method.Equals(QueryChildRelationshipsMethodName) &&
                                                                                 TestUtils.GetPropertyValue <Guid>(m.Need, "StartNodeId").Equals(_orgA1) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").From.Equals(mockUtcNow) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").To == null &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "LinkRelationshipTypes").Single().Equals(BusinessToBusinessRelationshipType) &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "NodeTypes").Single().Equals(AssetTypeOrganisation)
                                                                                 ),
                                         ResponseStyle.WholeSolution,
                                         It.IsAny <Func <string, bool> >()
                                         ), Times.Exactly(2) //We called get value twice, which would have cached it. but cache time set to zero which means the call would have been made twice as the cache would have been immediately invalidated.
                                     );

            _backplaneMock.Verify(x => x.Send(It.Is <OrganisationHierarchyCacheItem>(oti => oti.OrganisationId != Guid.Empty)));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }
        public void GetValue_WithValidKeyAlreadyInCache_MessageIsOnlyPublishedOnceAndCacheIsUsedThereafter()
        {
            var key = _orgA1;

            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution, It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse {
                Solution = JsonConvert.SerializeObject(_relationshipSampleData)
            });

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            var resultFromPublishingMessage = sut.GetValue(key);
            var resultFromCachedItem        = sut.GetValue(key);

            Assert.IsNotNull(resultFromPublishingMessage);
            Assert.IsTrue(ResultDataTreeIsCorrect(resultFromPublishingMessage));

            Assert.IsNotNull(resultFromCachedItem);
            Assert.IsTrue(ResultDataTreeIsCorrect(resultFromCachedItem));

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <object, Relationship> >(m =>
                                                                                 m.Method.Equals(QueryChildRelationshipsMethodName) &&
                                                                                 TestUtils.GetPropertyValue <Guid>(m.Need, "StartNodeId").Equals(_orgA1) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").From.Equals(mockUtcNow) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").To == null &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "LinkRelationshipTypes").Single().Equals(BusinessToBusinessRelationshipType) &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "NodeTypes").Single().Equals(AssetTypeOrganisation)
                                                                                 ),
                                         ResponseStyle.WholeSolution,
                                         It.IsAny <Func <string, bool> >()
                                         ), Times.Once //Even though we called GetValue twice, we only published a message once proving the entry was cached.
                                     );

            _backplaneMock.Verify(x => x.Send(It.Is <OrganisationHierarchyCacheItem>(oti => oti.OrganisationId != Guid.Empty)));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }
        public void AddOrUpdate_WithInitialAddEntry_ThenUpdateEntry_AddsAndUpdatesEntryCorrectlyAndNoMessagesArePublished()
        {
            var key          = new Guid("bc44ffe6-0533-47c8-986b-e40347a4d072");
            var initialValue = new OrganisationHierarchyCacheItem {
                OrganisationId = key, ChildOrganisations = null, Metadata = null
            };
            var updatedValue = new OrganisationHierarchyCacheItem {
                OrganisationId = key, ChildOrganisations = new List <OrganisationHierarchyCacheItem>(), Metadata = new CaseInsensitiveDictionary {
                    { "key1", "value1" }
                }
            };

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            sut.AddOrUpdate(key, initialValue);
            Assert.AreEqual(initialValue, sut.GetValue(key));

            sut.AddOrUpdate(key, updatedValue);
            Assert.AreEqual(updatedValue, sut.GetValue(key));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }
        public void GetValue_WithMatchingKeyNotInInCache_WithMultipleMultilevelRelationships_PublishesMesageOntoBusButReturnsItem()
        {
            var key = _orgA1;

            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution, It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse {
                Solution = JsonConvert.SerializeObject(_relationshipSampleData)
            });

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            var result = sut.GetValue(key);

            Assert.IsNotNull(result);
            Assert.IsTrue(ResultDataTreeIsCorrect(result));

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <object, Relationship> >(m =>
                                                                                 m.Method.Equals(QueryChildRelationshipsMethodName) &&
                                                                                 TestUtils.GetPropertyValue <Guid>(m.Need, "StartNodeId").Equals(_orgA1) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").From.Equals(mockUtcNow) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").To == null &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "LinkRelationshipTypes").Single().Equals(BusinessToBusinessRelationshipType) &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "NodeTypes").Single().Equals(AssetTypeOrganisation)),
                                         ResponseStyle.WholeSolution,
                                         It.IsAny <Func <string, bool> >()
                                         ), Times.Exactly(1)
                                     );

            _backplaneMock.Verify(x => x.Send(It.Is <OrganisationHierarchyCacheItem>(oti => oti.OrganisationId != Guid.Empty)));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }
        public void GetValue_WithNoMatchingKeyInCache_NoRelationshipsInRelationshipResponse_PublishesGetOrganisationMessage_CachesResponseCorrectlyAndReturnsResult()
        {
            var key = _orgA1;

            //first message to get relationships
            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution,
                                        It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse {
                Solution = JsonConvert.SerializeObject(new List <Relationship>())
            });

            //second message to get organisation
            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <Guid, OrganisationHierarchyCacheItem> >(), ResponseStyle.FirstOrDefault,
                                        null))
            .Returns(new JsonBusResponse
            {
                Solution = JsonConvert.SerializeObject(new
                {
                    OrganisationId = _orgA1,
                    Metadata       = new CaseInsensitiveDictionary {
                        { "key1", "value1" }
                    }
                })
            });

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            var result = sut.GetValue(key);

            Assert.IsNotNull(result);
            Assert.AreEqual(_orgA1, result.OrganisationId);

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <object, Relationship> >(m =>
                                                                                 m.Method.Equals(QueryChildRelationshipsMethodName) &&
                                                                                 TestUtils.GetPropertyValue <Guid>(m.Need, "StartNodeId").Equals(_orgA1) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").From.Equals(mockUtcNow) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").To == null &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "LinkRelationshipTypes").Single().Equals(BusinessToBusinessRelationshipType) &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "NodeTypes").Single().Equals(AssetTypeOrganisation)),
                                         ResponseStyle.WholeSolution,
                                         It.IsAny <Func <string, bool> >()
                                         ), Times.Exactly(1)
                                     );

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <Guid, OrganisationHierarchyCacheItem> >(m =>
                                                                                                 m.Method.Equals(GetOrganisationMethodName) &&
                                                                                                 m.Need.Equals(_orgA1)),
                                         ResponseStyle.FirstOrDefault,
                                         null),
                                     Times.Exactly(1));

            _backplaneMock.Verify(x => x.Send(It.Is <OrganisationHierarchyCacheItem>(oti => oti.OrganisationId.Equals(_orgA1))));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }
        public void GetValue_RelationshipsReturnedFromQueryChildRelationshipsDoNotContainRequestedOrganisationIdAsAParent_LogsAndThrowsException()
        {
            const string error = "The expected root node for the tree should be a parent and should not appear as a child in any relationship.";

            var key = _orgA1;

            var invalidRelationships = new List <Relationship>
            {
                new Relationship {
                    ChildNodeId = Guid.NewGuid(), ParentNodeId = Guid.NewGuid()
                },
                new Relationship {
                    ChildNodeId = Guid.NewGuid(), ParentNodeId = Guid.NewGuid()
                }
            };

            _requestStoreMock.Setup(x => x.PublishAndWaitForResponse(
                                        It.IsAny <Message <object, Relationship> >(), ResponseStyle.WholeSolution, It.IsAny <Func <string, bool> >()))
            .Returns(new JsonBusResponse {
                Solution = JsonConvert.SerializeObject(invalidRelationships)
            });

            var mockUtcNow = new DateTime(2017, 2, 2, 4, 3, 1);

            _dateTimeProviderMock.Setup(x => x.UtcNow).Returns(mockUtcNow);

            var sut = new Core.OrganisationHierarchyCache.OrganisationHierarchyCache(_loggerMock.Object, _requestStoreMock.Object, _dateTimeProviderMock.Object, _backplaneMock.Object, _configurationManagerMock.Object);

            try
            {
                sut.GetValue(key);
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual(ex.Message, error);
            }

            _requestStoreMock.Verify(x =>
                                     x.PublishAndWaitForResponse(
                                         It.Is <Message <object, Relationship> >(m =>
                                                                                 m.Method.Equals(QueryChildRelationshipsMethodName) &&
                                                                                 TestUtils.GetPropertyValue <Guid>(m.Need, "StartNodeId").Equals(_orgA1) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").From.Equals(mockUtcNow) &&
                                                                                 TestUtils.GetPropertyValue <RelationshipDateRange>(m.Need, "Active").To == null &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "LinkRelationshipTypes").Single().Equals(BusinessToBusinessRelationshipType) &&
                                                                                 TestUtils.GetPropertyValue <string[]>(m.Need, "NodeTypes").Single().Equals(AssetTypeOrganisation)
                                                                                 ),
                                         ResponseStyle.WholeSolution,
                                         It.IsAny <Func <string, bool> >()
                                         ), Times.Once
                                     );

            _loggerMock.Verify(x => x.Error("OrganisationHierarchyCache.ConvertRelationshipsToOrganisationTreeItem",
                                            It.Is <LogItem[]>(li => li[0].Key.Equals("Error") &&
                                                              li[0].Value.Invoke().Equals(error) &&
                                                              li[1].Key.Equals("rootNode") &&
                                                              li[1].Value.Invoke().Equals(_orgA1.ToString())
                                                              )));

            _requestStoreMock.VerifyNoOtherCalls();
            _backplaneMock.VerifyNoOtherCalls();
        }