Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.net core session unit test

I hava a problem with unit testing asp.net core mvc controller! the problem is that in my controller, i use sessions:

[HttpPost]
public IActionResult OpretLobby(LobbyViewModel lobby)
{
    try
    {
        //find brugeren der har lavet lobby
        var currentUser = HttpContext.Session.GetObjectFromJson<User>("user");
        //save as a lobby
        ILobby nyLobby = new Lobby(currentUser.Username)
        {
            Id = lobby.Id
        };
        SessionExtension.SetObjectAsJson(HttpContext.Session, lobby.Id, nyLobby);
        //add to the list
        _lobbyList.Add(nyLobby);
        return RedirectToAction("Lobby","Lobby",lobby);
    }

this all works perfectly well online on the server, nothing wrong here. BUT when it comes to the demand of unit testing this whole thing, its not so perfect anymore.

basicly the problem is, that i cant get access to my session from a test.. i have tryed in many ways to create mocks and what not, but most of the solutions work for .net framework, and not for .net core for some reason! please help im in pain!

note:

i used a dummy version of a test to isolate this problem:

[Test]
public void TestIsWorking()
{
    SessionExtension.SetObjectAsJson(uut.HttpContext.Session, "user", _savedUser);
    //ViewResult result = uut.OpretLobby(lobbyViewModel) as ViewResult;

    //Assert.AreEqual("OpretLobby", result.ViewName);
    Assert.AreEqual(1,1);
}

goes wrong also here trying to set the session for a user :/

like image 765
Nicholas Ladefoged Avatar asked Oct 21 '25 05:10

Nicholas Ladefoged


1 Answers

It seems that GetObjectFromJson is an extension method. If so, we could not mock static method easily.

I normally create an abstraction for that kind of scenario. Then register it in DI container, and inject the dependency to the controller.

Startup.cs

public class Startup
{
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddScoped<IUserSession, UserSession>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        ...
    }
    ...
}

Abstraction

public class User
{
    public string Username { get; set; }
}

public interface IUserSession
{
    User User { get; }
}

public class UserSession : IUserSession
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserSession(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public User User => _httpContextAccessor.HttpContext.Session.GetObjectFromJson<User>("user");
}

public static class SessionExtensions
{
    public static User GetObjectFromJson<User>(
        this ISession sesson, string json) where User : new()
    {
        return new User(); // Dummy extension method just to test OP's code
    }
}

Controller

public class HomeController : Controller
{
    private readonly IUserSession _userSession;

    public HomeController(IUserSession userSession)
    {
        _userSession = userSession;
    }

    public IActionResult OpretLobby()
    {
        var currentUser = _userSession.User;
        return View(currentUser);
    }
}

}

Unit Tests

using AspNetCore.Controllers;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;

namespace XUnitTestProject1
{
    public class HomeControllerTests
    {
        private readonly User _user;

        public HomeControllerTests()
        {
            _user = new User {Username = "johndoe"};
        }

        [Fact]
        public void OpretLobby_Test()
        {
            // Arrange
            var mockUserSession = new Mock<IUserSession>();
            mockUserSession.Setup(x => x.User).Returns(_user);
            var sut = new HomeController(mockUserSession.Object);

            // Act
            var result = sut.OpretLobby();

            // Assert
            var viewResult = Assert.IsType<ViewResult>(result);
            var user = Assert.IsType<User>(viewResult.Model);
            Assert.Equal(_user.Username, user.Username);
        }
    }
}
like image 135
Win Avatar answered Oct 24 '25 22:10

Win