我的应用程序是 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 UserManager
自 UserManager
需要 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 .
您可以做两件事......
- 使用EF Core InMemoryDatabase进行集成测试,这是为了集成测试而制作的
- 重构您的代码
IQueryable<T>
不会泄漏到存储库或命令/查询处理程序之外
从技术上讲,可以创建一个实现 AsAsyncEnumerable<T>
的列表。但我还没有尝试过,很可能无法使用 list.AsQueryable()
因为它将列表包装在下面的某个位置...
关于asp.net - asp.net core 中的单元测试 UserManager<IdentityUser>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43843342/