关于c#:Asp.net核心会话单元测试

Asp.net core session unit test

我有问题,与ASP.NET MVC的控制器单元测试的核心。那是我的问题:我使用的会话控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[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);
    }

本厂perfectly全井的在线服务器,这里没什么错。但当它吃的东西全单元测试需求(这不是完美的,它的操作系统了。

basicly的问题是,我不能把我从访问的测试会话。在许多方面,我有一个很mocks创建不到什么,但大多数.NET框架的解决方案和不工作的核心,是.NET的一些原因。请帮助我在痛苦!

注意:

我使用的版本的虚拟试验对分离这一问题:

1
2
3
4
5
6
7
8
9
[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);
}

这里的错误也会想设置会话的用户。


似乎GetObjectFromJson是一种扩展方法。如果是这样,我们就不能轻易地模拟静态方法。

我通常为这种场景创建一个抽象。然后在DI容器中注册它,并将依赖项注入控制器。

创业公司

1
2
3
4
5
6
7
8
9
10
11
12
public class Startup
{
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddScoped<IUserSession, UserSession>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        ...
    }
    ...
}

抽象化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
    }
}

控制器2

}

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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);
        }
    }
}


@尼古拉斯·拉德福格

嘿,我建议您在需要从会话中获取一些内容时使用集成测试

ASP.NET核心有一个很棒的TestHostnuget包,它可以帮助您使用集成方式验证逻辑进行测试。

尝试添加以下代码段

1
2
3
4
5
6
7
8
9
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库没有模拟静态方法的能力,所以存在很多问题。我认为在您的情况下使用集成测试会更容易一些

祝你好运!


胜利解决了!这是最后的测试代码,如果有人想知道的话!谢谢!

1
2
3
4
5
6
7
8
9
10
            // 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);


按照win所说的那样做之后,我得到的viewresult为空。

单元测试桩法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        [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);

        }

柱法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 [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");
            }
           
        }

会话扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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);
        }
    }

希望你能帮得上忙