使用 C# Moq 模拟 ElasticSearch 客户端

Mocking an ElasticSearch client using C# Moq

我正在测试我的 class ElasticUtility,它需要一个 ElasticClient 的实例才能正常工作,所以我模拟了这样的 class 并将其注入到ElasticUtility 实例 (utility)

    private ElasticUtility utility;
    private Mock<IElasticClient> elasticClientMock;
    private string elasticSearchIndexName;

    elasticClientMock = new Mock<IElasticClient>();
    utility = new UhhElasticUtility(elasticClientMock.Object);

这是实际测试代码:

[Test]
public void GetGetPvDataClientReturnNull()
{
    // arrange
    var groupId = "groupid";
    var startTime = new DateTime(2015, 08, 17, 13, 30, 00);
    var endTime = new DateTime(2015, 08, 17, 13, 40, 00);
    
    // act
    utility.GetPvData(groupId, startTime, endTime);

    // assert
    elasticClientMock.Verify(ec => ec.Search<SegmentRecord>(It.IsAny<Nest.ISearchRequest>()), Times.Once());
}

当 Moq 库在模拟的 ElastiClient.

中调用 .Search() 方法时,我得到一个 Null 引用异常

编辑:

ElasticUtility的构造函数:

    protected ElasticUtility(IElasticClient elasticClient, string elasticIndexName)
    {
        this.ElasticClient = elasticClient;
        this.ElasticIndexName = elasticIndexName;
    }

编辑:GetPvData() 方法:

    public IEnumerable<dynamic> GetPvData(string groupId, DateTime startTime, DateTime endTime)
    {
        var res = ElasticClient.Search<SegmentRecord>(s => s
            .Index(ElasticIndexName)
            .Filter(f =>
                f.Term(t => t.HistoryId, groupId) &&
                f.Range(i =>
                    i.OnField(a => a.DateTime).LowerOrEquals(startTime))).SortAscending(p => p.DateTime).Size(1)).Documents.ToList();

        return res.ToArray();
    }

发生 NullReferenceException 是因为您没有在 search 方法上指定行为。您的 search 方法 returns null 然后您调用 .Document null。

指定行为的方式如下:

elasticClientMock.Setup(x => x.Search<SegmentRecord>(
                             It.IsAny</* put here the right Func */>))
        .Returns( /* put here the instance you want to return */);

你必须用正确的类型替换我的评论。

代码来自 .git 此处:https://gist.github.com/netoisc/5d456850d79f246685fee23be2469155

var people = new List<Person>
{
    new Person { Id = 1 },
    new Person { Id = 2 },
};

var hits = new List<IHit<Person>>
{
    new Mock<IHit<Person>>().Object
};

var mockSearchResponse = new Mock<ISearchResponse<Person>>();
mockSearchResponse.Setup(x => x.Documents).Returns(people);
mockSearchResponse.Setup(x => x.Hits).Returns(hits);

var mockElasticClient = new Mock<IElasticClient>();

mockElasticClient.Setup(x => x
    .Search(It.IsAny<Func<SearchDescriptor<Person>, ISearchRequest>>()))
.Returns(mockSearchResponse.Object);