如何在asp net core中模拟Session对象

时间:2017-11-09 13:38:37

标签: c# unit-testing asp.net-core moq asp.net-core-mvc-2.0

我正在使用moq框架编写单元测试。我在基本控制器Data[2]中调用一个方法,它将使用setsession()设置会话,我还有一个方法SetString("userdata",object)将获得会话。

getsession()

我收到了var sessionMock = new Mock<ISession>(); sessionMock.Setup(s => s.GetString("userdata")).Returns(Object);--failing sessionMock.Setup(s => s.SetString("userdata",object));--failing s.GetString中的错误消息。

由于s.SetStringGetString是扩展方法,我可能需要使用其他方式来处理它。

你能帮帮我吗?

3 个答案:

答案 0 :(得分:7)

根据ISession Extensions source code GetStringSetString是扩展方法

public static void SetString(this ISession session, string key, string value)
{
    session.Set(key, Encoding.UTF8.GetBytes(value));
}

public static string GetString(this ISession session, string key)
{
    var data = session.Get(key);
    if (data == null)
    {
        return null;
    }
    return Encoding.UTF8.GetString(data);
}

public static byte[] Get(this ISession session, string key)
{
    byte[] value = null;
    session.TryGetValue(key, out value);
    return value;
}

您需要模拟ISession.SetISession.TryGetValue才能让扩展方法按预期执行。

//Arrange
var sessionMock = new Mock<ISession>();
var key = "userdata";
var value = new byte[0];

sessionMock.Setup(_ => _.Set(key, It.IsAny<byte[]>()))
    .Callback<string, byte[]>((k,v) => value = v);

sessionMock.Setup(_ => _.TryGetValue(key, out value))
    .Returns(true);

答案 1 :(得分:0)

感谢Nkosi的出色回答。就我而言,我必须在单元测试中处理GetInt32和SetInt32扩展方法。根据下面的source code是实现

public static void SetInt32(this ISession session, string key, int value)
        {
            var bytes = new byte[]
            {
                (byte)(value >> 24),
                (byte)(0xFF & (value >> 16)),
                (byte)(0xFF & (value >> 8)),
                (byte)(0xFF & value)
            };
            session.Set(key, bytes);
        }

public static int? GetInt32(this ISession session, string key)
        {
            var data = session.Get(key);
            if (data == null || data.Length < 4)
            {
                return null;
            }
            return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
        }

因此,按照我的回答,我必须做一些修改,如下所示。

 Mock<ISession> sessionMock = new Mock<ISession>();
        var key = "FY";
        int fy = 2020;
        var value =  new byte[]
        {
            (byte)(fy >> 24),
            (byte)(0xFF & (fy >> 16)),
            (byte)(0xFF & (fy >> 8)),
            (byte)(0xFF & fy)
        };

  sessionMock.Setup(_ => _.TryGetValue(key, out value)).Returns(true);

我在任何地方都找不到此内容,因此请在此处共享,以免对遇到相同问题的人有所帮助。

答案 2 :(得分:-1)

这是我要问的灵魂

)创建一个新的模拟ISession和新的模拟HttpContext

//Arrange
var mockContext = new Mock<HttpContext>();
var mockSession = new Mock<ISession>();

)创建会话值

SomeClass sessionUser = new SomeClass() { Property1 = "MyValue" };
var sessionValue = JsonConvert.SerializeObject(sessionUser);
byte[] dummy = System.Text.Encoding.UTF8.GetBytes(sessionValue);

)安装程序模拟返回序列化的obj

mockSession.Setup(x => x.TryGetValue(It.IsAny<string>(), out dummy)).Returns(true); //the out dummy does the trick
mockContext.Setup(s => s.Session).Returns(mockSession.Object);

)注入到mvc httpcontext(在我的情况下是Page而不是典型的控制器)

_classUnderTest.PageContext = new Microsoft.AspNetCore.Mvc.RazorPages.PageContext();
_classUnderTest.PageContext.HttpContext = mockContext.Object;

现在一切就绪,当我点击会话getvalue时,我收到了序列化对象的信息

希腊 尼克