asp.net - asp.net core 中的单元测试 UserManager<IdentityUser>

标签 asp.net entity-framework unit-testing asp.net-core

我的应用程序是 ASP.NET Core 1.0 Web API。我想测试以下方法(截图):

public async Task<bool> GetClientsAsync()
{
     foreach (var user in await this.clientAdapter.Users().ToListAsync())
     {
          return true;
     }
     return false;
}

通常是clientAdapter正在调用UserManager<IdentityUser>的属性(property) Users 。所以“真正的”clientAdapter 的代码看起来像这样:

public IQueryable<IdentityUser> Users()
{
    return this.userManager.Users;
}

现在当我测试clientAdapter时看起来像下面这样:

private readonly List<IdentityUser> clientList;

public TestClientAdapter(){
     this.clientList= this.CreateClientList();
}

public IQueryable<IdentityUser> Users()
{
     return this.userList.AsQueryable();
}

方法的返回类型Users()必须是IQueryable<IdentityUser>因为那是原始类 UserManager<IdentityUser> 的返回值。现在,如果我执行测试,一旦遇到 foreach 循环,我就会收到以下错误(问题是 ToListAsync() 调用):

System.NotSupportedException: "Store does not implement IQueryableUserStore<TUser>."

如果我改变循环

foreach (var user in await this.clientAdapter.Users().ToListAsync())
{
    return true;
}

foreach (var user in this.clientAdapter.Users().ToList())
{
    return true;
}

一切正常。

我的问题:

我无法 mock UserManagerUserManager需要 UserStore这需要 DBContext我不知道如何 mock 。即使可以 mock DBContext ,我认为这会将我的单元测试变成集成测试,但我不希望这样。另外,这可能不值得付出努力。所以我不能只和一个被 mock 的 Usermanager 一起工作并从中获取数据。

我的问题:

是否可以在不更改我要测试的方法的情况下使单元测试通过?

编辑

@CodeCaster:

注入(inject)的clientAdapter现在看起来如下(截图):

  public class TestClientAdapter: IClientAdapter, IQueryableUserStore<IdentityUser>
  {
  private readonly List<IdentityUser> clientList

  private UserManager<IdentityUser> testUserManager;

  public TestClientAdapter: ()
  {
     clientList= this.CreateclientList();

     this.testUserManager = new UserManager<IdentityUser>(this, null, null, null, null, null, null, null, null);
  }

  public IQueryable<IdentityUser> Users()
  {
     return this.testUserManager.Users;
  }

  IQueryable<IdentityUser> IQueryableUserStore<IdentityUser>.Users
  {
     get
     {
        return this.clientList.AsQueryable();
     }
  }

现在我又得到了一个 Exception :

"System.InvalidOperationException" in System.Private.CoreLib.ni.dll"

最佳答案

ToListAsync (以及其他异步方法,如 AnyAsync 等)不是来自 IQueryable<T> 的标准 Linq2SQL(又名 System.Linq.* )扩展方法.

它是 EntityFramework 的一部分,因此它假设某些先决条件,因此它不能与可查询列表一起使用。基本上它是 query.AsAsyncEnumerable() 的包装。和AsAsyncEnumerable检查 IAsyncEnumerable<TSource> 是否存在和/或 IAsyncEnumerableAccessor<TSource>如果不存在 throws the invalid operation exception .

您可以做两件事......

  1. 使用EF Core InMemoryDatabase进行集成测试,这是为了集成测试而制作的
  2. 重构您的代码 IQueryable<T>不会泄漏到存储库或命令/查询处理程序之外

从技术上讲,可以创建一个实现 AsAsyncEnumerable<T> 的列表。但我还没有尝试过,很可能无法使用 list.AsQueryable()因为它将列表包装在下面的某个位置...

关于asp.net - asp.net core 中的单元测试 UserManager<IdentityUser>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43843342/

相关文章:

javascript - 使用javascript在Gridview中设置下拉列表的值

asp.net - 将 ASP.NET Core 1.1 升级到 ASP.NET Core 2.0

c# - ASP.NET Entity Framework Code First 环境间迁移过程

java - Apache Camel 测试

.net - ASP.NET View 引擎不会执行我的代码片段

entity-framework - 生成 ScaffoldingConnectionFactory 时出错

entity-framework - 从 Azure 移动应用获取具有嵌套复杂类型的模型

c# - 集成测试是否应该重做使用模拟的单元测试?

在类中使用的 Python 模拟 os.environ

javascript - 从内联代码 aspx 调用 javascript 函数