Asp.net core 带有会话和测试的.NET核心ASP.NET控制器
我的web项目在.NETCore2.x中。在登录控制器中,在登录之后,我在会话中保存一个令牌,以便跨页面使用该令牌 当我想测试所有控制器时,我的问题就开始了。如果我从测试调用控制器,HttpContext.Session为null 然后我找到了这个模拟会话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,
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编译。变量声明必须是字节[]。