public void TryGetCanonicalUrl_CanonicalUrl_ReturnsTrue(
            bool appendTrailingSlash,
            bool lowercaseUrls,
            string requestUrl)
        {
            var context = GetResourceExecutingContext(requestUrl);
            var filter  = new RedirectToCanonicalUrlAttributeMock(appendTrailingSlash, lowercaseUrls);

            var isCanonical = filter.TryGetCanonicalUrl(context, out string canonicalUrl);

            Assert.True(
                isCanonical,
                $"{nameof(appendTrailingSlash)}={appendTrailingSlash} {nameof(lowercaseUrls)}={lowercaseUrls} {nameof(requestUrl)}={requestUrl}");
            Assert.Null(canonicalUrl);
        }
        public void TryGetCanonicalUrl_AppendTrailingSlashAndLowercaseUrlsAndIsNotCanonicalUrl_ReturnsFalseAndCanonicalUrl(
            bool appendTrailingSlash,
            bool lowercaseUrls,
            string requestUrl,
            string expectedCanonicalUrl)
        {
            var context = GetResourceExecutingContext(requestUrl);
            var filter  = new RedirectToCanonicalUrlAttributeMock(appendTrailingSlash, lowercaseUrls);

            var isCanonical = filter.TryGetCanonicalUrl(context, out string canonicalUrl);

            Assert.False(
                isCanonical,
                $"{nameof(appendTrailingSlash)}={appendTrailingSlash} {nameof(lowercaseUrls)}={lowercaseUrls} {nameof(requestUrl)}={requestUrl}");
            Assert.Equal(expectedCanonicalUrl, canonicalUrl);
        }