【问题标题】:Mocking an ElasticSearch client using C# Moq使用 C# Moq 模拟 ElasticSearch 客户端
【发布时间】:2015-11-11 12:46:04
【问题描述】:

我正在测试我的类ElasticUtility,它需要ElasticClient 的实例才能正常工作,所以我模拟了此类并将其注入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();
    }

【问题讨论】:

  • 请添加UhhElasticUtility的C'tor和GetPvData的实现
  • 会不会是被保护了?
  • 没有受保护的 C'tor 不是问题...但我询问了 UhhElasticUtility C'tor 和 GetPvData...
  • 这是 GetPvData() 实现
  • 问题是.Documents你没有设置期望,然后搜索返回null...

标签: c# unit-testing testing elasticsearch moq


【解决方案1】:

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

指定行为的方式如下:

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

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

【讨论】:

  • 我无法创建 Nest.ISearchResponse 的实例以将其传递给 .Returns() 方法。
  • 如果我写: var test = Nest.ISearchResponse();它说“此时接口名称无效”。哦,这是一个界面!
  • 即使使用 Nest.SearchResponse 也不起作用
  • 使用Moq创建Nest.ISearchResponse&lt;SegmentRecord&gt;();的实例或者创建一个自定义类型,如果你使用Moq确保你没有忘记初始化假对象属性。
  • 是的,但是没有用。我将响应嘲笑为: var response = new Mock>(); elasticClientMock.Setup(ec => ec.Search(It.IsAny())).Returns(response.Object);但 .Search() 函数不断返回 null
【解决方案2】:

代码来自 .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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多