public async Task GetNumberOfAddressesPerPostcodeAsync()
        {
            CancellationToken        cancellationToken        = new CancellationToken();
            PostcodeAndAddressGetter postcodeAndAddressGetter = new PostcodeAndAddressGetter(_repository.Object, _qasAddressGetter.Object, _postcodesWithoutAddressesCache.Object);

            List <string> postcodes = new List <string>()
            {
                "NG11AA",  // in DB
                "NG11AB",  // addresses aren't in DB, but will be retrieved through QAS
                "NG1 1AC", // will be filtered out because of postcodes without addresses cache
                "NG1 1AD", // will be added to postcodes without addresses cache
            };

            IEnumerable <PostcodeWithNumberOfAddressesDto> result = await postcodeAndAddressGetter.GetNumberOfAddressesPerPostcodeAsync(postcodes, cancellationToken);

            _repository.Verify(x => x.GetNumberOfAddressesPerPostcodeAsync(It.Is <IEnumerable <string> >(y => y.Count() == 3 && y.Contains("NG1 1AA") && y.Contains("NG1 1AB") && y.Contains("NG1 1AD"))), Times.Once);


            _qasAddressGetter.Verify(x => x.GetPostCodesAndAddressesFromQasAsync(It.Is <IEnumerable <string> >(y => y.Count() == 2 && y.Contains("NG1 1AB") && y.Contains("NG1 1AD")), It.IsAny <CancellationToken>()), Times.Once); // doesn't include NG1 1AC because it's been filtered out


            _postcodesWithoutAddressesCache.Verify(x => x.AddRange(It.Is <IEnumerable <string> >(y => y.Count() == 1 && y.Contains("NG1 1AD"))));

            Assert.AreEqual(2, result.Count());

            Assert.AreEqual(3, result.FirstOrDefault(x => x.Postcode == "NG1 1AA").NumberOfAddresses);
            Assert.AreEqual(2, result.FirstOrDefault(x => x.Postcode == "NG1 1AB").NumberOfAddresses);
        }
        public async Task GetPostcodeAsync()
        {
            CancellationToken        cancellationToken        = new CancellationToken();
            PostcodeAndAddressGetter postcodeAndAddressGetter = new PostcodeAndAddressGetter(_repository.Object, _qasAddressGetter.Object, _postcodesWithoutAddressesCache.Object);

            PostcodeDto result = await postcodeAndAddressGetter.GetPostcodeAsync("NG11AA", cancellationToken);

            _repository.Verify(x => x.GetPostcodesAsync(It.Is <IEnumerable <string> >(y => y.Count() == 1 && y.Contains("NG1 1AA"))), Times.Once);

            Assert.AreEqual(1, result.AddressDetails.Count());
            Assert.AreEqual("1_addressline1", result.AddressDetails.FirstOrDefault().AddressLine1);
            Assert.AreEqual("1_addressline2", result.AddressDetails.FirstOrDefault().AddressLine2);
            Assert.AreEqual("1_addressline1", result.AddressDetails.FirstOrDefault().AddressLine3);
            Assert.AreEqual("1_locality", result.AddressDetails.FirstOrDefault().Locality);
        }
        public async Task GetPostcodesAsync_PostCodesAreRetrievedFromQasAndDatabase()
        {
            CancellationToken        cancellationToken        = new CancellationToken();
            PostcodeAndAddressGetter postcodeAndAddressGetter = new PostcodeAndAddressGetter(_repository.Object, _qasAddressGetter.Object, _postcodesWithoutAddressesCache.Object);

            List <string> postcodes = new List <string>()
            {
                "NG11AA",  // in DB
                "NG11AB",  // addresses aren't in DB, but will be retrieved through QAS
                "NG1 1AC", // will be filtered out when calling QAS because of postcodes without addresses cache
                "NG1 1AD", // will be added to postcodes without addresses cache
            };

            IEnumerable <PostcodeDto> result = await postcodeAndAddressGetter.GetPostcodesAsync(postcodes, cancellationToken);

            _repository.Verify(x => x.GetPostcodesAsync(It.Is <IEnumerable <string> >(y => y.Count() == 4 && y.Contains("NG1 1AA") && y.Contains("NG1 1AB") && y.Contains("NG1 1AC") && y.Contains("NG1 1AD"))), Times.Once);


            _qasAddressGetter.Verify(x => x.GetPostCodesAndAddressesFromQasAsync(It.Is <IEnumerable <string> >(y => y.Count() == 2 && y.Contains("NG1 1AB") && y.Contains("NG1 1AD")), It.IsAny <CancellationToken>()), Times.Once); // doesn't include NG1 1AC because it's been filtered out before calling QAS

            _postcodesWithoutAddressesCache.Verify(x => x.AddRange(It.Is <IEnumerable <string> >(y => y.Count() == 1 && y.Contains("NG1 1AD"))));

            Assert.AreEqual(2, result.Count());

            List <AddressDetailsDto> returnedMissingPostCodeAddressFromDb  = result.FirstOrDefault(x => x.Postcode == "NG1 1AA").AddressDetails;
            List <AddressDetailsDto> returnedMissingPostCodeAddressFromQas = result.FirstOrDefault(x => x.Postcode == "NG1 1AB").AddressDetails;

            Assert.AreEqual(1, returnedMissingPostCodeAddressFromDb.Count());
            Assert.AreEqual("1_addressline1", returnedMissingPostCodeAddressFromDb.FirstOrDefault().AddressLine1);
            Assert.AreEqual("1_addressline2", returnedMissingPostCodeAddressFromDb.FirstOrDefault().AddressLine2);
            Assert.AreEqual("1_addressline1", returnedMissingPostCodeAddressFromDb.FirstOrDefault().AddressLine3);
            Assert.AreEqual("1_locality", returnedMissingPostCodeAddressFromDb.FirstOrDefault().Locality);

            Assert.AreEqual(2, returnedMissingPostCodeAddressFromQas.Count());
            Assert.AreEqual("2_addressline1", returnedMissingPostCodeAddressFromQas.FirstOrDefault(x => x.AddressLine1 == "2_addressline1").AddressLine1);
            Assert.AreEqual("2_addressline2", returnedMissingPostCodeAddressFromQas.FirstOrDefault(x => x.AddressLine1 == "2_addressline1").AddressLine2);
            Assert.AreEqual("2_addressline1", returnedMissingPostCodeAddressFromQas.FirstOrDefault(x => x.AddressLine1 == "2_addressline1").AddressLine3);
            Assert.AreEqual("2_locality", returnedMissingPostCodeAddressFromQas.FirstOrDefault(x => x.AddressLine1 == "2_addressline1").Locality);
        }