Модульный тест ядра сессии Asp.net - PullRequest
0 голосов
/ 27 апреля 2018

У меня проблема с модульным тестированием asp.net core mvc controller! проблема в том, что в моем контроллере я использую сессии:

[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);
    }

все это прекрасно работает в режиме онлайн на сервере, здесь все в порядке. НО, когда дело доходит до требования модульного тестирования, все это уже не так идеально.

По сути, проблема в том, что я не могу получить доступ к своему сеансу из теста. Я пытался разными способами создавать фиктивные изменения, а что нет, но большинство решений работают для .net framework, а не для .net ядро по какой-то причине! Пожалуйста, помогите мне от боли!

примечание:

Я использовал фиктивную версию теста, чтобы изолировать эту проблему:

[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);
}

тоже идет не так, пытаясь установить сеанс для пользователя: /

Ответы [ 4 ]

0 голосов
/ 01 ноября 2018

@ Николо-ladefoged

Эй, я бы рекомендовал вам использовать интеграционное тестирование, когда вам нужно получить контент из сессии

Ядро asp.net имеет замечательный пакет TestHost nuget, который может помочь вам проверить логику, используя способ интеграции для тестирования.

Попробуйте добавить фрагмент кода ниже

TestServer server = new TestServer(new WebHostBuilder()
            .UseStartup<Startup>()
            .ConfigureTestServices(services =>
            {
                services.AddHttpContextAccessor();
            }));
var client = server.CreateClient();

var response = await client.GetAsync(""); // I'm using GetAsync just for sample

вот, пожалуйста! У вас будет настоящий сеанс, который вы можете проверить

Кстати, библиотека Moq не умеет имитировать статические методы, поэтому возникает много проблем. Я думаю, что будет проще использовать интеграционный тест в вашей ситуации

удачи!

0 голосов
/ 27 апреля 2018

после того, как Win сказал, что я получаю viewResult как ноль.

Метод пост-тестового модуля

        [Test]
        public void OpretLobby_Post()
        {            
            
            // Arrange
            var mockUserSession = new Mock<IUserSession>();
            mockUserSession.Setup(x => x.User).Returns(_savedUser);
            var sut = new LobbyController(FakeSwagCommunication,mockUserSession.Object);

            // Act
            var result = sut.OpretLobby(_lobbyViewModel) as ViewResult;

            // Assert

            //var user = (User)result.Model;
            Assert.AreEqual("Lobby",result.ViewName);

        }

Почтовый метод

 [HttpGet]
        public IActionResult OpretLobby()
        {
            return View("OpretLobby");
        }

        [HttpPost]
        public IActionResult OpretLobby(LobbyViewModel lobby)
        {
            
            try
            {
                //find brugeren der har lavet lobby
                var currentUser = _userSession.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);

            }
            catch (ArgumentException)
            {
                return RedirectToAction("OpretLobby");
            }
            
        }

Расширения сеанса

public interface IUserSession
    {
        User User { get; set; }

    }

    public class UserSession : IUserSession
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

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

        public User User
        {
            get => _httpContextAccessor.HttpContext.Session.GetObjectFromJson<User>("user");
            set => _httpContextAccessor.HttpContext.Session.SetObjectAsJson("user", value);
        }
    }

    public static class SessionExtension
    {
        public static void SetObjectAsJson(this ISession session, string key, object value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T GetObjectFromJson<T>(this ISession session, string key)
        {
            var value = session.GetString(key);

            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }
    }

Надеюсь, что вы можете помочь дальше

0 голосов
/ 28 апреля 2018

Win решил это! вот финальный тестовый код, если кому-то интересно! Большое спасибо!

            
            // Arrange
            var mockUserSession = new Mock<IUserSession>();
            mockUserSession.Setup(x => x.User).Returns(_savedUser);
            var sut = new LobbyController(FakeSwagCommunication,mockUserSession.Object);

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

            // Assert
            Assert.IsInstanceOf<RedirectToActionResult>(result);
0 голосов
/ 27 апреля 2018

Кажется, что GetObjectFromJson - это метод расширения. Если это так, мы не могли бы издеваться над статическим методом легко .

Обычно я создаю абстракцию для такого сценария. Затем зарегистрируйте его в контейнере DI и вставьте зависимость в контроллер.

Startup.cs

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

Абстракция

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
    }
}

Контроллер

public class HomeController : Controller
{
    private readonly IUserSession _userSession;

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

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

}

Юнит-тесты

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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...