Home > Software engineering >  How to write a test for the method which is a part of larger service?
How to write a test for the method which is a part of larger service?

Time:12-07

I have met a following problem: I have to write a test for a method which is a part of a service, but does not make use of other parts of said service, except for a two methods (which is called Remove and is presented below).

Method I need to write a test for takes in a cookie name. Then, based on that cookie name it gets from dictionary a consent category said cookie belongs to. After that there is IF statement which uses the HasCookieConsent method and determines if cookie should be removed, or not. If yes, it is removed by Remove method.

public void UpdateCookiesAccordingToConsent(string cookie)
{
    var cookiesConsentType = _httpOnlyCookies.FirstOrDefault(x => x.Key ==     
cookie).Value;

    if (!HasCookieConsent(cookiesConsentType) && _httpOnlyCookies.ContainsKey(cookie))
        {
            Remove(cookie);     
        }
}

Cookie categories are taken from dictionary:

private readonly Dictionary<string, CookiesConsentType> _httpOnlyCookies = new Dictionary<string, CookiesConsentType>()
{
    { CookieNames.VisitorCookieName,  CookiesConsentType.Statistic },
    { CookieNames.GoogleAnalyticsTrackingCookieName, CookiesConsentType.Statistic },
    { CookieNames.TaxonomyVisitorCookieName, CookiesConsentType.Statistic },
    { CookieNames.MarketoMunchkinTrackingCookieName, CookiesConsentType.Marketing },
};

Remove method:

public void Remove(string cookie)
{
    if (_httpContextAccessor.HttpContext == null)
    {
        return;
    }
    var options = new CookieOptions
    {
        HttpOnly = true,
            Secure = _httpContextAccessor.HttpContext.Request.IsHttps,
            Expires = DateTime.Now.AddDays(-1),
    };
    _httpContextAccessor.HttpContext.Response.Cookies.Append(cookie, string.Empty, options);
}

HasCookieConsent method:

private bool HasCookieConsent(CookiesConsentType consentType)
{
try
{
    var hasConsentCookie = _httpContextAccessor?.HttpContext?.Request?.Cookies?.ContainsKey("CookieConsent") ?? false;
        if (!hasConsentCookie)
        {
            return false;
        }

    var cookie = _httpContextAccessor.HttpContext.Request.Cookies["CookieConsent"] ?? string.Empty;

        if (string.IsNullOrWhiteSpace(cookie))
        {
            return false;
        }

    var cookieConsent = JsonConvert.DeserializeObject<CookieConsent>(cookie) ?? new CookieConsent();
        return consentType switch
        {
            CookiesConsentType.Preferences => cookieConsent.Preferences,
            CookiesConsentType.Marketing => cookieConsent.Marketing,
            CookiesConsentType.Statistic => cookieConsent.Statistics,
            CookiesConsentType.Necessary => cookieConsent.Necessary,
            _ => false,
        };
    }
    catch (Exception ex)
    {
        _logger.LogError("Could not deserialize cookie: {Exception}", ex);
        return false;
    }
}

Any tips on how to do it? I am using xUnit.

CodePudding user response:

try something like this.

[Test]
public void UpdateCookiesAccordingToConsent_CallsRemove_WhenHasCookieConsentIsFalseAndHttpOnlyCookiesContainsCookie()
{
    // Arrange
    var cookie = "testCookie";
    var cookiesConsentType = CookiesConsentType.Statistic;
    var httpOnlyCookies = new Dictionary<string, CookiesConsentType>()
    {
        { cookie, cookiesConsentType }
    };

    var service = new CookieService(httpOnlyCookies);
    service.HasCookieConsent(false);

    // Act
    service.UpdateCookiesAccordingToConsent(cookie);

    // Assert
    service.Remove(cookie);
}

CodePudding user response:

It seems like you want to write Unit test and not Integration tests. In order to do so you should mock the dependencies of your class, in this case HttpContextAccessor which is possible because it inherits from an interface. For instance you could use FakeItEasy:

var fakeContextAccessor = A.Fake<IHttpContextAccessor>();
fakeHttpContext = A.Fake<HttpContext>();
A.CallTo(() => fakeContextAccessor.HttpContext).Returns(fakeHttpContext)

You will just have to research a little how to exactly get it to return what your method needs. (https://fakeiteasy.github.io/)

After Arrange, you have to Act:

var sut = new CookieService();
sut.UpdateCookiesAccordingToConsent("cookie")

And either assert that the Remove Method was called or the cookie was removed by it. It really depends on what exactly you are trying to test here although one or the other might not be possible. You could try something like:

A.CallTo(_httpContextAccessor.HttpContext.Response.Cookies.Append(cookie, string.Empty, options).MustHaveHappend();

I hope this helps a little.

  • Related