如何模拟UserManager< IdentityUser> [英] How to mock UserManager<IdentityUser>
问题描述
我正在尝试找出如何向我的项目中添加单元测试.我认为最好从一个空白项目开始,并从头开始进行设计,而不是将其添加到我的主项目中.一旦了解了流程,我便可以开始重构我的项目以添加测试.
I am trying to work out how to add unit testing to my project. I thought it was best to start with a blank project and work it out from the start rather than adding it to my main project. Once I understand the process i figure i can start refactoring my project for adding testing.
因此,我创建了一个Web应用程序,并向其中添加了默认用户身份.
So i created a web application and added default user identity to it.
这给了我一个像这样的启动
This gave me a start up looking like this
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
然后我创建了一个简单的控制器,并在构造函数中传递了usermanager.
Then i created a simple controller and passed the usermanager in the constructor.
[Route("api/[controller]")]
[ApiController]
public class SweetController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
public SweetController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public async Task<int> NumberOfGummyBearsForUser(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
var userHasASweetTooth = await _userManager.IsInRoleAsync(user, "SweetTooth");
if (userHasASweetTooth)
{
return 100;
}
else
{
return 1;
}
}
}
单元测试
我一直想做的第一件事是模拟该用户管理器,但它不起作用.
Unit Test
The first thing i have been trying to do is mock this user manager but its not working.
public void Test1()
{
// Arrange
var mockUser = new Mock<UserManager<IdentityUser>>();
var userManager = new UserManager(mockRepo.Object); <-- error here see image below
var controller = new SweetController(userManager.Object);
// Act
var result = await controller.NumberOfGummyBearsForUser("123");
// Assert
Assert.Equal(100, result);
}
错误看起来像这样
我认为我需要通过更多的操作来创建该usermanager对象,但是我不确定我找到的所有教程都使用ApplicationUser而不是IdentityUser,所以我对如何模拟该对象感到困惑.
I think i need to pass more to create this usermanager object but i am not sure what all the tutorials i have found use ApplicationUser and not IdentityUser so i am at a loss as to how i can mock this object.
推荐答案
您只需
// Arrange
var mockUser = new Mock<UserManager<IdentityUser>>();
var controller = new SweetController(mockUser.Object);
您不需要
var userManager = new UserManager(mockRepo.Object); <-- error here see image below
完全
. mockUser
已经是模拟的UserManager<T>
,您可以通过mock.Object
放置模拟的实例.
at all. mockUser
is already the mocked UserManager<T>
, which you place a mocked instance via mock.Object
.
当模拟对象时,您不必使用其所有依赖关系实例化它(这将是集成测试),这就是模拟的重点(连同使方法返回所需的值并进行行为测试以确保您测试的代码调用了带有模拟对象特定参数的特定方法.
When you mock an object you don't have to instantiate it with all of its dependencies (that would be integration test), that's the point of mocking (along with making methods return a desired value and do behavior tests to make sure your tested code has called a specific method with specific parameter of the mocked object).
当然,上面的代码本身是行不通的,因为您没有为FindByIdAsync
和IsInRoleAsync
设置任何测试条件/返回值.您必须使用
Of course per se the above code won't work, since you didn't setup any test conditions/returns for FindByIdAsync
and IsInRoleAsync
. You have to setup these with
mockUser.Setup( userManager => userManager.FindByIdAsync(It.IsAny<string>()))
.ReturnsAsync(new IdentityUser { ... });
mockUser.Setup( userManager => userManager.IsInRoleAsync(It.IsAny<IdentityUser>(), "SweetTooth"))
.ReturnsAsync(true);
然后,无论何时调用该模拟,它都会返回您的预定义用户和预定义结果.
Then whenever the mock is called it returns your predefined user and a predefined result.
这篇关于如何模拟UserManager< IdentityUser>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!