如何使用 IConfiguration 测试带有令牌的 class
How to test a class with token using IConfiguration
我在 .Net 框架中使用 Xunit。这个 class 是 GenerateJWT 有一个参数是 User type (Object) 需要测试,我想模拟 IConfiguration Interface 但不知道它是否正确。目标是输入一个需要匹配字符串 result
的字符串 expect
public string GenerateJWT(User userInfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
return encodeToken;
}
下面这个class是我的测试,我用Mockclass来Mock IConfiguration接口那returns一个代码
[Fact]
public async Task GenerateJWT_Return_Token()
{
//Arrange
var mock_service = new Mock<IUserAdminService>();
var mock_config = new Mock<IConfiguration>();
User login = new User() { Id = 2, FullName = "abc", AddressDetail = "A", CityId = "123", DistrictId = "123", WardsId = "123", Password = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=", Gender = "male", Phone = "0123456789", DOB = "5/5/1999", Avatar = "" };
var x = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=";
mock_config.Setup(m => m["Jwt:Key"]).Returns(x);
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(x));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, login.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token= new JwtSecurityToken(
x,
x,
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
//Act
var service = new LoginAdminService(mock_config.Object, mock_service.Object);
string result = service.GenerateJWT(login);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
//Assert
Assert.Equal(encodeToken, result);
}
测试消息失败,不知如何处理。我需要你们的一些建议
这里的问题可能是GenerateJWT方法使用了DateTime.Now。
这是您无法直接控制的事情,并且会在测试 运行 时随时更改。在您的测试中,您还通过调用 DateTime.Now 创建了一个令牌,但要检查的令牌和生成的令牌之间可能仍然存在细微的毫秒差异。
如果您希望能够测试此方法,您将需要使用包装器 class 来提供当前时间。
这可能看起来像这样:
public interface IDateTimeProvider
{
DateTime Now { get; }
}
然后您需要更改 GenerateJWT 方法以也从外部接受 DateTimeProvider 实例:
public string GenerateJWT(User userInfo, IDateTimeProvider dateProvider)
{
...
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims,
expires: dateProvider.Now.AddMinutes(120),
signingCredentials: credentials);
...
}
这样您就可以完全控制测试中的所有内容:
[Fact]
public async Task GenerateJWT_Return_Token()
{
//Arrange
var mock_service = new Mock<IUserAdminService>();
var mock_config = new Mock<IConfiguration>();
var mockProvider = new Mock<IDateTimeProvider>();
User login = new User() { Id = 2, FullName = "abc", AddressDetail = "A", CityId = "123", DistrictId = "123", WardsId = "123", Password = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=", Gender = "male", Phone = "0123456789", DOB = "5/5/1999", Avatar = "" };
var x = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=";
mock_config.Setup(m => m["Jwt:Key"]).Returns(x);
mockProvider.Setup(m => m.Now).Returns(new DateTime(2022, 4, 22, 16, 0, 0));
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(x));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, login.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token= new JwtSecurityToken(
x,
x,
claims,
expires: mockProvider.Object.Now.AddMinutes(120),
signingCredentials: credentials);
//Act
var service = new LoginAdminService(mock_config.Object, mock_service.Object);
string result = service.GenerateJWT(login, mockProvider.Object);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
//Assert
Assert.Equal(encodeToken, result);
}
我在 .Net 框架中使用 Xunit。这个 class 是 GenerateJWT 有一个参数是 User type (Object) 需要测试,我想模拟 IConfiguration Interface 但不知道它是否正确。目标是输入一个需要匹配字符串 result
的字符串 expectpublic string GenerateJWT(User userInfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
return encodeToken;
}
下面这个class是我的测试,我用Mockclass来Mock IConfiguration接口那returns一个代码
[Fact]
public async Task GenerateJWT_Return_Token()
{
//Arrange
var mock_service = new Mock<IUserAdminService>();
var mock_config = new Mock<IConfiguration>();
User login = new User() { Id = 2, FullName = "abc", AddressDetail = "A", CityId = "123", DistrictId = "123", WardsId = "123", Password = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=", Gender = "male", Phone = "0123456789", DOB = "5/5/1999", Avatar = "" };
var x = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=";
mock_config.Setup(m => m["Jwt:Key"]).Returns(x);
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(x));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, login.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token= new JwtSecurityToken(
x,
x,
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
//Act
var service = new LoginAdminService(mock_config.Object, mock_service.Object);
string result = service.GenerateJWT(login);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
//Assert
Assert.Equal(encodeToken, result);
}
测试消息失败,不知如何处理。我需要你们的一些建议
这里的问题可能是GenerateJWT方法使用了DateTime.Now。 这是您无法直接控制的事情,并且会在测试 运行 时随时更改。在您的测试中,您还通过调用 DateTime.Now 创建了一个令牌,但要检查的令牌和生成的令牌之间可能仍然存在细微的毫秒差异。
如果您希望能够测试此方法,您将需要使用包装器 class 来提供当前时间。 这可能看起来像这样:
public interface IDateTimeProvider
{
DateTime Now { get; }
}
然后您需要更改 GenerateJWT 方法以也从外部接受 DateTimeProvider 实例:
public string GenerateJWT(User userInfo, IDateTimeProvider dateProvider)
{
...
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims,
expires: dateProvider.Now.AddMinutes(120),
signingCredentials: credentials);
...
}
这样您就可以完全控制测试中的所有内容:
[Fact]
public async Task GenerateJWT_Return_Token()
{
//Arrange
var mock_service = new Mock<IUserAdminService>();
var mock_config = new Mock<IConfiguration>();
var mockProvider = new Mock<IDateTimeProvider>();
User login = new User() { Id = 2, FullName = "abc", AddressDetail = "A", CityId = "123", DistrictId = "123", WardsId = "123", Password = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=", Gender = "male", Phone = "0123456789", DOB = "5/5/1999", Avatar = "" };
var x = "03RCzu/LT/48EeliJG9L/ZS/ITwGAYUUoALJSePkG5k=";
mock_config.Setup(m => m["Jwt:Key"]).Returns(x);
mockProvider.Setup(m => m.Now).Returns(new DateTime(2022, 4, 22, 16, 0, 0));
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(x));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, login.Phone),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token= new JwtSecurityToken(
x,
x,
claims,
expires: mockProvider.Object.Now.AddMinutes(120),
signingCredentials: credentials);
//Act
var service = new LoginAdminService(mock_config.Object, mock_service.Object);
string result = service.GenerateJWT(login, mockProvider.Object);
var encodeToken = new JwtSecurityTokenHandler().WriteToken(token);
//Assert
Assert.Equal(encodeToken, result);
}