我已经编写了一个测试,用于验证一小部分新功能,该功能调用大型中间件功能,其中包含大量逻辑,将一种类型的用户(ASP网络成员用户)转换为内部用户(SystemUser) 。这是一个混乱的系统,但我不能把它撕掉,因此是新的测试。
我的测试调用了一个GetAllActiveUsers()
方法,该方法调用了几个层并最终进入导致问题的枚举。该测试有一个模拟的实体框架datacontext Mock<localEntities> mockDb
,其设置如下:
[SetUp]
public void Setup()
{
var mockUserSet = new Mock<DbSet<User>>();
this.mockDb = new Mock<localEntities>();
this.mockMembershipService = new Mock<IMembershipService>();
this.mockRoleService = new Mock<IRoleService>();
this.mockUserAgreementRelation = new Mock<DbSet<UserAgreementRelation>>();
this.testUsers = this.CreateSystemUsers();
this.mockDb.Setup(m => m.User).Returns(mockUserSet.Object);
mockUserAgreementRelation.SetupAllProperties();
var agreementRelations = this.testUsers.Select(u => new UserAgreementRelation() { AgentUserID = u.UserId, IsDeleted = null });
mockUserAgreementRelation.As<IQueryable<UserAgreementRelation>>().Setup(ua => ua.GetEnumerator()).Returns(agreementRelations.GetEnumerator());
this.mockDb.Setup(m => m.UserAgreementRelation).Returns(mockUserAgreementRelation.Object);
}
在我的测试中,我设置了一些用户并调用var testActiveUsers = testRepo.GetAllActiveUsers();
来调用问题行。
这是我感到困惑的地方。
测试通过以下代码:
var agreementRelations = databaseContext.UserAgreementRelation().ToList();
var userAgreementFromDB = agreementRelations
.FirstOrDefault(x => x.AgentUserID == ramsUser.UserId && (x.IsDeleted == null || !(bool)x.IsDeleted));
但是使用此代码失败:
var userAgreementFromDB = databaseContext.UserAgreementRelation
.FirstOrDefault(x => x.AgentUserID == ramsUser.UserId && (x.IsDeleted == null || !(bool)x.IsDeleted));
此外,如果我调试并逐步执行代码,我可以在模拟的UserAgreementRelation 上使用快速监视。我第一次看到我正在测试的每个用户的UserAgreementRelation。如果我再次运行手表,即使代码没有提前,枚举也不会产生任何结果。我猜这与这个问题有关。但是,由于我不知道为什么正在发生,我不知道它是如何导致这个问题的。
请记住,更简单的代码(没有ToList())是生产代码。它目前运行正常,但我的测试失败了。由于这是一个直接的数据库调用,枚举整个UserAgreementRelation表不是一个可行的解决方案。
建议?
答案 0 :(得分:2)
我不确定我是否遇到了这个问题,因为你没有详细说明它是如何失败的&#34;。但也许你应该更改部分:
.Setup(ua => ua.GetEnumerator()).Returns(agreementRelations.GetEnumerator())
成:
.Setup(ua => ua.GetEnumerator()).Returns(() => agreementRelations.GetEnumerator())
原因是,如果您测试的代码多次调用GetEnumerator()
,则Moq不应该分发旧的&#34;使用过的&#34 ;枚举器实例可能已经提前到最后并可能被处置。相反,Moq应该重新运行Func<>
,我的箭头() => agreementRelations.GetEnumerator()
,以获取尚未提升(MoveNext()
)或关闭(Dispose()
)的新枚举器。< / p>
提问者通知我(在下面的评论中)他还需要Setup
IQueryable
{{1}} Provider
的Expression
。
答案 1 :(得分:0)
我一直用这样的东西,试试这个。
var userAgreementFromDB = databaseContext.UserAgreementRelation
.Where(x => x.AgentUserID == ramsUser.UserId && (x.IsDeleted == null || !(bool)x.IsDeleted)).FirstOrDefault();