Moq + xunit + asp.net core: service return 空值

Moq + xunit + asp.net core: service return null value

我在 asp.net 核心应用程序中使用 xUnit 作为测试 运行ner。 这是我的测试理论:

[Theory(DisplayName = "Search advisors by advisorId"),
        ClassData(typeof(SearchAdvisorsByIdTestData))]
    public async void SearchAdvisors_ByAdvisorId(int brokerDealerId, FilterParams filter)
    {
        // Arrange
        var _repositoryMock = new Mock<IRepository>();
        // Do this section means we bypass the repository layer
        _repositoryMock
             .Setup(x => x.SearchAdvisors(filter.CID.Value, new AdvisorSearchOptions
             {
                 SearchKey = filter.SeachKey,
                 AdvisorId = filter.AdvisorId,
                 BranchId = filter.BranchId,
                 City = filter.City,
                 Skip = filter.Skip,
                 Limit = filter.Limit,
                 RadiusInMiles = filter.Limit,
                 Longitude = filter.Longitude,
                 Latitude = filter.Latitude
             }))
             .Returns(Task.FromResult<SearchResults<Advisor>>(
                new SearchResults<Advisor>()
                {
                    Count = 1,
                    Limit = 0,
                    Skip = 0,
                    ResultItems = new List<SearchResultItem<Advisor>>() {
                        //some initialize here
                    }
                })
            );

        _advisorService = new AdvisorService(_repositoryMock.Object, _brokerDealerRepositoryMock, _brokerDealerServiceMock);

        // Action
        var model = await _advisorService.Search(brokerDealerId, filter);

        Assert.True(model.AdvisorResults.Count == 1);
        Assert.True(model.AdvisorResults[0].LocationResults.Count > 0);
    }

这样的服务

public async Task<ViewModelBase> Search(int brokerDealerId, FilterParams filter)
    {
        var opts = new AdvisorSearchOptions
        {
            SearchKey = filter.SeachKey,
            AdvisorId = filter.AdvisorId,
            BranchId = filter.BranchId,
            City = filter.City,
            Skip = filter.Skip,
            Limit = filter.Limit,
            RadiusInMiles = filter.Limit,
            Longitude = filter.Longitude,
            Latitude = filter.Latitude
        };

        var searchResults = await _repository.SearchAdvisors(filter.CID.Value, opts);  // line 64 here

        if (searchResults.Count == 0 && Utils.IsZipCode(filter.SeachKey))
        {


        }

        //Some other code here

        return model;
    }

问题出现在服务中的 运行 行 64 之后。尽管我已经在测试中模拟了 _repository,但我总是得到 searchResults 的空值。

我哪里错了?

提前致谢。

SearchAdvisors() 模拟的参数匹配器不起作用,因为您传递了 AdvisorSearchOptions 的不同实例。第一个实例在 _repositoryMock.Setup() 语句中创建,第二个实例在 Search() 方法本身中创建。

有几种方法可以解决这个问题:

1.If 您不关心验证传递给存储库的实例 of AdvisorSearchOptions 是否正确填充,只需在模拟设置中使用 It.IsAny<AdvisorSearchOptions>() 匹配器:

_repositoryMock.Setup(x => x.SearchAdvisors(filter.CID.Value, It.IsAny<AdvisorSearchOptions>()))
    .Returns(/*...*/);

2.In 之前的情况测试不会验证 AdvisorSearchOptions 是否正确填写。为此,您可以覆盖 AdvisorSearchOptions class 中的 Object.Equals() 方法,以便模拟调用将匹配不同的实例:

public class AdvisorSearchOptions
{
    // ...

    public override bool Equals(object obj)
    {
        var cmp = obj as AdvisorSearchOptions;
        if (cmp == null)
        {
            return false;
        }

        return SearchKey == cmp.SearchKey && AdvisorId == cmp.AdvisorId &&
            /* ... compare all other fields here */
    }
}

3.Another 验证传递给 mock 的对象的方法是通过 Mock 回调保存实例,然后比较所需字段:

AdvisorSearchOptions passedSearchOptions = null;
_repositoryMock
     .Setup(x => x.SearchAdvisors(filter.CID.Value, It.IsAny<AdvisorSearchOptions>()))
     .Returns(Task.FromResult<SearchResults<Advisor>>(
        new SearchResults<Advisor>()
        {
            Count = 1,
            Limit = 0,
            Skip = 0,
            ResultItems = new List<SearchResultItem<Advisor>>() {
                //some initialize here
            }
        })
    )
    .Callback<int, AdvisorSearchOptions>((id, opt) => passedSearchOptions = opt);

//  Action
//  ...

Assert.IsNotNull(passedSearchOptions);
Assert.AreEqual(filter.SearchKey, passedSearchOptions.SearchKey);
Assert.AreEqual(filter.AdvisorId, passedSearchOptions.AdvisorId);
// Check all other fields here
// ...