Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core 带有会话和测试的.NET核心ASP.NET控制器_Asp.net Core_Mocking_Asp.net Core Mvc - Fatal编程技术网

Asp.net core 带有会话和测试的.NET核心ASP.NET控制器

Asp.net core 带有会话和测试的.NET核心ASP.NET控制器,asp.net-core,mocking,asp.net-core-mvc,Asp.net Core,Mocking,Asp.net Core Mvc,我的web项目在.NETCore2.x中。在登录控制器中,在登录之后,我在会话中保存一个令牌,以便跨页面使用该令牌 当我想测试所有控制器时,我的问题就开始了。如果我从测试调用控制器,HttpContext.Session为null 然后我找到了这个模拟会话 public class MockHttpSession : ISession { Dictionary<string, object> sessionStorage = new Dictionary<string,

我的web项目在.NETCore2.x中。在登录控制器中,在登录之后,我在会话中保存一个令牌,以便跨页面使用该令牌

当我想测试所有控制器时,我的问题就开始了。如果我从测试调用控制器,HttpContext.Session为null

然后我找到了这个模拟会话

public class MockHttpSession : ISession
{
    Dictionary<string, object> sessionStorage = new Dictionary<string, object>();
    public object this[string name]
    {
        get { return sessionStorage[name]; }
        set { sessionStorage[name] = value; }
    }

    string ISession.Id
    {
        get {
            throw new NotImplementedException();
        }
    }
    bool ISession.IsAvailable
    {
        get {
            throw new NotImplementedException();
        }
    }
    IEnumerable<string> ISession.Keys
    {
        get { return sessionStorage.Keys; }
    }

    void ISession.Clear()
    {
        sessionStorage.Clear();
    }

    Task ISession.CommitAsync(CancellationToken cancellationToken 
                                      = default(CancellationToken))
    {
        throw new NotImplementedException();
    }

    Task ISession.LoadAsync(CancellationToken cancellationToken 
                                      = default(CancellationToken))
    {
        throw new NotImplementedException();
    }

    void ISession.Remove(string key)
    {
        sessionStorage.Remove(key);
    }

    void ISession.Set(string key, byte[] value)
    {
        sessionStorage[key] = value;
    }

    bool ISession.TryGetValue(string key, out byte[] value)
    {
        if (sessionStorage[key] != null)
        {
            value = Encoding.ASCII.GetBytes(sessionStorage[key].ToString());
            return true;
        }
        else
        {
            value = null;
            return false;
        }
    }
}
是否有另一种简单的方法来保存跨控制器和可测试的会话的一些值

更新

如您所见,with my mock的值在会话中,但GetString返回System.Byte[]而不是值

您可以使用现有的ISession扩展方法,这些方法可能适用于您的实现:

using Microsoft.AspNetCore.Http;

var result = HttpContext.Session.GetString("name");
查看本课程:

您也可以根据需要添加新的

也看看这个问题

更新:

看起来您的TryGetValue与扩展方法不一致,扩展方法将尝试将字节[]存储到字典中。恶魔就在那条线上:

value=Encoding.ASCII.GetBytessessionStorage[key].ToString; 您使用的是ASCII,而不是UTF8,似乎还需要进行双重转换

我建议对方法进行如下更改:

bool ISession.TryGetValue(string key, out byte[] value)
{
    object storageValue = null;
    if(sessionStorage.TryGetValue(key, out storageValue))
    {
        var bytes = storageValue as byte[];

        if(bytes != null)
        {
            value = bytes;
            return true;
        }

        value = Encoding.UTF8.GetBytes(storageValue.ToString());
        return true;
    }

    value = null;
    return false;
}
您还可以考虑使用byte[]作为字典值,而不是对象

您可以使用现有的ISession扩展方法,这些方法可能适用于您的实现:

using Microsoft.AspNetCore.Http;

var result = HttpContext.Session.GetString("name");
查看本课程:

您也可以根据需要添加新的

也看看这个问题

更新:

看起来您的TryGetValue与扩展方法不一致,扩展方法将尝试将字节[]存储到字典中。恶魔就在那条线上:

value=Encoding.ASCII.GetBytessessionStorage[key].ToString; 您使用的是ASCII,而不是UTF8,似乎还需要进行双重转换

我建议对方法进行如下更改:

bool ISession.TryGetValue(string key, out byte[] value)
{
    object storageValue = null;
    if(sessionStorage.TryGetValue(key, out storageValue))
    {
        var bytes = storageValue as byte[];

        if(bytes != null)
        {
            value = bytes;
            return true;
        }

        value = Encoding.UTF8.GetBytes(storageValue.ToString());
        return true;
    }

    value = null;
    return false;
}

您不妨考虑使用byte[]作为字典值,而不是对象。在我的例子中,我必须在单元测试中处理GetInt32和SetInt32扩展方法。如下所示为实施情况

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

我在任何地方都找不到它,所以在这里共享,以防它对有相同问题的人有所帮助。

在我的情况下,我必须在单元测试中处理GetInt32和SetInt32扩展方法。如下所示为实施情况

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);
我在任何地方都找不到这个,所以在这里共享,以防对有相同问题的人有所帮助。

使用object storageValue=null;不会为TryGetValue编译。变量声明需要为字节[]。使用对象storageValue=null;不会为TryGetValue编译。变量声明必须是字节[]。