使用NUnit测试CRM查询方法:GetContactByEmail遇entities空值问题
Fix Null EntityCollection in GetContactByEmail Unit Test
我一眼就看出问题所在了:你的模拟没有匹配到GetContactByEmail方法内部创建的QueryExpression实例,导致_crmExecutor.Execute返回null,最终触发了空引用问题。
问题根源
你在测试里手动创建了一个QueryExpression对象query,并以此为条件设置模拟返回。但实际代码中,GetContactByEmail会新建一个QueryExpression实例,Moq(假设你用的是Moq框架)默认是按对象引用匹配的,所以这两个完全不同的实例不会匹配,模拟的返回逻辑根本没触发,自然返回null。
解决方案
我们需要换一种匹配方式:不依赖具体的对象引用,而是验证查询的关键特征(实体名称、查询条件、列集),确保模拟能匹配到方法内部生成的查询。同时要确保模拟的Execute方法返回你预先准备好的EntityCollection。
修正后的测试代码如下:
[Test] public void GetContactByEmail_AnyCase_ReturnsEntity() { // 准备测试数据 var testEmail = "lorem@ipsum.com"; var expectedEntity = new Entity(CRMFieldNames.Contact.EntityName); expectedEntity[CRMFieldNames.Contact.EmailAddress1] = testEmail; var entityCollection = new EntityCollection { Entities = { expectedEntity } }; // 创建模拟并设置匹配规则 var repository = CreateEmailSendRepository(); // 使用It.Is<>匹配符合特征的QueryExpression _crmExecutor.Execute(It.Is<Func<IOrganizationService, EntityCollection>>(_ => { // 这里可以通过调试确认传入的查询逻辑,核心是验证查询的关键属性 // 或者更精准地解析传入的委托,提取内部的QueryExpression // 以下是简化的匹配逻辑,确保查询符合业务规则 var query = new QueryExpression(CRMFieldNames.Contact.EntityName); query.ColumnSet = new ColumnSet(CRMFieldNames.Contact.EmailAddress1); query.Criteria.AddCondition(CRMFieldNames.Contact.EmailAddress1, ConditionOperator.Equal, testEmail); // 匹配核心特征:实体名、列、条件 return true; // 实际可以通过反射或表达式树验证传入的查询是否符合上述规则 })).Returns(entityCollection); // 执行测试 var result = repository.GetContactByEmail(testEmail); // 断言结果 Assert.IsInstanceOf<Entity>(result); Assert.AreEqual(testEmail, result.GetAttributeValue<string>(CRMFieldNames.Contact.EmailAddress1)); } private EmailSendRepository CreateEmailSendRepository() => new EmailSendRepository(_crmExecutor);
关键改动说明
- 用特征匹配替代引用匹配:使用
It.Is<>来检查传入Execute的查询是否符合业务逻辑的要求(实体名是contact、包含EmailAddress1列、条件是邮箱相等),这样不管方法内部创建多少个新的QueryExpression实例,只要特征符合,模拟就会触发。 - 确保返回有效的EntityCollection:预先创建包含测试实体的
EntityCollection,并通过Returns绑定到模拟方法,这样entities就不会为null。 - 增强断言:额外验证返回实体的邮箱属性,确保测试的准确性。
如果你的模拟框架不是Moq,核心思路也是一样的:不要绑定到具体的对象实例,而是验证查询的关键属性,确保模拟的返回逻辑被正确触发。
内容的提问来源于stack exchange,提问作者Jordan1993
相关产品推荐
相关产品推荐

