public async Task CreateAsync_WhenUrlExistsForTargetUrl_UrlIsReused()
        {
            var expectedUrl = GenerateUrl();

            _urlServiceMock.Setup(m => m.FindWithTargetUrlAsync(It.IsAny <string>(), It.IsAny <string>()))
            .ReturnsAsync(expectedUrl);

            var repository = new ShortUrlRepository(_urlServiceMock.Object, _wordsServiceMock.Object, _configuration);
            var actual     = await repository.CreateAsync("https://localhost/", "en", PartOfSpeech.Adjective);

            Assert.Equal(expectedUrl.DateCreated, actual.DateCreated);
            Assert.Equal(expectedUrl.TargetUrl, actual.TargetUrl);
            _urlServiceMock.Verify(m => m.FindWithTargetUrlAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Once);
            _wordsServiceMock.Verify(m => m.GetWordByIdAsync <Adverb>(expectedUrl.AdverbId), Times.Once);
            _wordsServiceMock.Verify(m => m.GetWordByIdAsync <Adjective>(expectedUrl.AdjectiveId), Times.Once);
            _wordsServiceMock.Verify(m => m.GetWordByIdAsync <Noun>(expectedUrl.NounId), Times.Once);
        }
        public async Task CreateAsync_WhenCannotReuse_UsesRandomWordsUntilAvailable()
        {
            var expectedAdverb    = GenerateWord <Adverb>(false, false);
            var expectedAdjective = GenerateWord <Adjective>(false, false);
            var expectedNoun      = GenerateWord <Noun>(false, false);

            _wordsServiceMock.Setup(m => m.GetRandomWordAsync <Adverb>(It.IsAny <string>(), It.IsAny <bool>()))
            .ReturnsAsync(expectedAdverb);
            _wordsServiceMock.Setup(m => m.GetRandomWordAsync <Adjective>(It.IsAny <string>(), It.IsAny <bool>()))
            .ReturnsAsync(expectedAdjective);
            _wordsServiceMock.Setup(m => m.GetRandomWordAsync <Noun>(It.IsAny <string>(), It.IsAny <bool>()))
            .ReturnsAsync(expectedNoun);
            _urlServiceMock.SetupSequence(m => m.IsAvailableAsync(It.IsAny <Url>()))
            .ReturnsAsync(false).ReturnsAsync(false).ReturnsAsync(false).ReturnsAsync(false).ReturnsAsync(false)
            .ReturnsAsync(true);
            const string targetUrl    = "https://localhost/";
            const string languageCode = "en";

            var repository = new ShortUrlRepository(_urlServiceMock.Object, _wordsServiceMock.Object, _configuration);
            var actual     = await repository.CreateAsync(targetUrl, languageCode, PartOfSpeech.Noun);

            Assert.Equal(expectedAdverb.Id, actual.Adverb.Id);
            Assert.Equal(expectedAdverb.Value, actual.Adverb.Value);
            Assert.Equal(expectedAdjective.Id, actual.Adjective.Id);
            Assert.Equal(expectedAdjective.Value, actual.Adjective.Value);
            Assert.Equal(expectedNoun.Id, actual.Noun.Id);
            Assert.Equal(expectedNoun.Value, actual.Noun.Value);
            Assert.Equal("https://localhost/", actual.BaseDomain);
            Assert.Equal(targetUrl, actual.TargetUrl);
            Assert.Equal($"https://localhost/{expectedAdverb.Value}{expectedAdjective.Value}{expectedNoun.Value}",
                         actual.FullUri.ToString());
            _urlServiceMock.Verify(m => m.FindWithTargetUrlAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Once);
            _urlServiceMock.Verify(m => m.IsAvailableAsync(It.IsAny <Url>()), Times.Exactly(6));
            _urlServiceMock.Verify(m => m.SaveUrlAsync(It.IsAny <Url>()), Times.Once);
            _wordsServiceMock.Verify(m => m.GetRandomWordAsync <Adverb>(It.IsAny <string>(), It.IsAny <bool>()), Times.Exactly(6));
            _wordsServiceMock.Verify(m => m.GetRandomWordAsync <Adjective>(It.IsAny <string>(), It.IsAny <bool>()), Times.Exactly(6));
            _wordsServiceMock.Verify(m => m.GetRandomWordAsync <Noun>(It.IsAny <string>(), It.IsAny <bool>()), Times.Exactly(6));
        }