简体   繁体   English

为什么 XUnit 测试用例会抛出“Moq.MockException:调用失败”错误,而我的输入都是正确的?

[英]Why XUnit Test case throwing "Moq.MockException : invocation failed" error, where my inputs all are correct?

while interface mocking I am trying to send with actual inputs in model object, but getting failure with虽然接口 mocking 我正在尝试使用 model object 中的实际输入发送,但出现故障

Moq.MockException : ISearchRepo.GetEsDataWithBoolByAggregation<IndexVM>(BoolMustMatchAggregationIM) invocation failed with mock behavior Strict.
    All invocations on the mock must have a corresponding setup.

error message.错误信息。

Mock method for interface input object (which is sending same like in manual)接口输入的模拟方法 object (与手动发送相同)

private BoolMustMatchAggregationIM GetBoolMustMatchAggregationIMMockData()
{
    var objInputs = GetTopologyTabularApplyFilterMockData();
    var studentFieldValue = objInputs.StudentId != null ? string.Join(',', objInputs.StudentId) : string.Empty;
    BoolMustMatchAggregationIM topoplogyApplyFilter = new BoolMustMatchAggregationIM()
    {
        From = objInputs.From,
        Size = objInputs.Size,
        IndexName = ElasticSearchIndexConstant.Index,
        FirstField = DataConstant.MarketField,
        FirstFieldValue = objInputs.Market,
        SecondField = DataConstant.StudentField,
        SecondFieldValue = studentFieldValue,
        ThirdField = DataConstant.SubjectField,
        ThirdFieldValue = objInputs.SubjectId != null ? objInputs.SubjectId : null,
        FourthField = DataConstant.SiteIdFieldName,
        FourthFieldValue = objInputs.SiteId != null ? objInputs.SiteId[0] : null,
        OperatorType = DataConstant.NestAndOperator,
        CardinalField = DataConstant.CardinalField,
        SumName = DataConstant.SumName,
        MinimumMatch = DataConstant.One
    };
    return topoplogyApplyFilter;
}

Mock method for output object from interface从接口模拟 output object 方法

private IEnumerable<SiteSubjectIndexVM> GetSiteSubjectIndexClassMockData()
{
    List<SiteSubjectDetails> objListSiteSubject = new List<SiteSubjectDetails>();
    SiteSubjectDetails objSiteSubject = new SiteSubjectDetails { SubjectId = 4002453 };
    objListSiteSubject.Add(objSiteSubject);

    List<SiteSubjectIndexVM> objListSiteSubjectIndexClass = new List<SiteSubjectIndexVM>();

    SiteSubjectIndexVM objSiteSubjectIndexClass = new SiteSubjectIndexVM()
    {
        Id = 123,
        StudentId = "SE123",
        Longitude = -122.51m,
        Latitude = 47.66m,
        Region = "Selected",
        SiteId = "SE03D123",
        HasSubjectSites = 1,
        Market = "HNK",
        TimeStamp = new DateTime(2022, 08, 07, 11, 02, 51, 167),
        AAVStatus = "Selected"
    };
    objListSiteSubjectIndexClass.Add(objSiteSubjectIndexClass);

     objSiteSubjectIndexClass = new SiteSubjectIndexVM()
    {
         Id = 456,
         SiteId = "SE04D456",
         Subjects = objListSiteSubject,
         StudentId = "SE456",
         Latitude = 47.74m,
         Longitude = -122.15m,
         Market = "WGL",
         TimeStamp = new DateTime(2022, 08, 07, 11, 02, 51, 167),
         Region = "WEST",
         HasSubjectSites = 1
     };
    objListSiteSubjectIndexClass.Add(objSiteSubjectIndexClass);

    return objListSiteSubjectIndexClass;
}

Test Case测试用例

[Fact]
public async Task GetTabularApplyFilterAsync_WhenMarketIsNotNull_ReturnsSiteSubjectsIndexFromES()
{
    //Arrange
    var objRepoIM = GetBoolMustMatchAggregationIMMockData();
    var objRepoVM = GetSiteSubjectIndexClassMockData().Where(x=>x.Id== 72337696).ToList();
    var objIMapperVM = GetSiteSubjectIndexMockData().Where(x => x.Id == 72337696).ToList();
    var objServiceIM = GetTabularApplyFilterMockData();
    objServiceIM.StudentId = null; objServiceIM.SubjectId = null; objServiceIM.SiteId = null;

    //Action
    _mockISearchRepo.Setup(x => x.GetEsDataWithBoolByAggregationAsync<SiteSubjectIndexVM>(objRepoIM)).ReturnsAsync(objRepoVM);
    _mockMapper.Setup(x => x.Map<IEnumerable<SiteSubjectIndex>>(objRepoVM)).Returns(objIMapperVM);
    var subjectService = this.CreateSearchService();
    var result = await subjectService.GetTabularApplyFilterAsync(objServiceIM).ConfigureAwait(false);

    //Assert
    Assert.NotNull(result);
    Assert.Equal(result, objIMapperVM);
    _mockRepository.VerifyAll();
}

by _mockIElasticSearchRepo.Setup(x => x.GetEsDataWithBoolByAggregationAsync<SiteLinkIndexVM>(It.IsAny<BoolMustMatchAggregationIM>())).ReturnsAsync(objRepoVM); by _mockIElasticSearchRepo.Setup(x => x.GetEsDataWithBoolByAggregationAsync<SiteLinkIndexVM>(It.IsAny<BoolMustMatchAggregationIM>())).ReturnsAsync(objRepoVM); error get resolved, but why?错误得到解决,但为什么? where I have given correct input model with correct values.我已经给出了正确的输入 model 和正确的值。

The error message signals that there is no setup for the call.错误消息表明没有设置呼叫。 The following setup will be met, if the parameter is equal to the object that you created:如果参数等于您创建的 object,则将满足以下设置:

_mockISearchRepo.Setup(x => x.GetEsDataWithBoolByAggregationAsync<SiteSubjectIndexVM>(objRepoIM)).ReturnsAsync(objRepoVM);

Most likely, the call to GetEsDataWithBoolByAggregationAsync in the code under test does not use the exact same instance that you created in your test, but creates an instance of its own.最有可能的是,在被测代码中对GetEsDataWithBoolByAggregationAsync的调用不使用您在测试中创建的完全相同的实例,而是创建了自己的实例。 Hence check will fail because it is not the same object and the setup is not matched.因此检查将失败,因为它不是相同的 object 并且设置不匹配。

You can work around this by defining the setup so that you check the parameters dynamically, eg您可以通过定义设置来解决此问题,以便动态检查参数,例如

_mockISearchRepo
  .Setup(x => x.GetEsDataWithBoolByAggregationAsync<SiteSubjectIndexVM>(It.Is<BoolMustMatchAggregationIM>(y => y.IndexName == ElasticSearchIndexConstant.Index))
  .ReturnsAsync(objRepoVM);

In above sample, I have only included a very simple check for the index name.在上面的示例中,我只对索引名称进行了非常简单的检查。 You can extend the expression to check the input more thoroughly.您可以扩展表达式以更彻底地检查输入。

By using this approach, the setup will be matched as soon as the expression returns true so this also works if the code under test creates the instance that is used as the parameter.通过使用这种方法,一旦表达式返回 true,设置就会匹配,因此如果被测代码创建用作参数的实例,这也可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM