Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Moq的ElasticClient代码覆盖率_C#_Unit Testing_<img Src="//i.stack.imgur.com/RUiNP.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">elasticsearch_Moq_Code Coverage - Fatal编程技术网 elasticsearch,moq,code-coverage,C#,Unit Testing,elasticsearch,Moq,Code Coverage" /> elasticsearch,moq,code-coverage,C#,Unit Testing,elasticsearch,Moq,Code Coverage" />

C# 使用Moq的ElasticClient代码覆盖率

C# 使用Moq的ElasticClient代码覆盖率,c#,unit-testing,elasticsearch,moq,code-coverage,C#,Unit Testing,elasticsearch,Moq,Code Coverage,我试图通过单元测试来分析代码覆盖率,我目前正在使用Moq库来执行单元测试,不知何故,我进入了一条错误的道路,我想知道下面的场景是否适用于使用Moq 下面是一段代码 public interface ISearchWorker { void DeleteIndex(string indexName); T GetClient<T>(); } public class ElasticSearchWorker : ISearchWorker { public v

我试图通过单元测试来分析代码覆盖率,我目前正在使用Moq库来执行单元测试,不知何故,我进入了一条错误的道路,我想知道下面的场景是否适用于使用Moq

下面是一段代码

public interface ISearchWorker
{
    void DeleteIndex(string indexName);

    T GetClient<T>();
}

public class ElasticSearchWorker : ISearchWorker
{
    public void DeleteIndex(string indexName)
    {
        IElasticClient elasticClient = GetClient<IElasticClient>();

        if (elasticClient.IndexExists(indexName).Exists)
        {
            _ = elasticClient.DeleteIndex(indexName);
        }
    }

    public T GetClient<T>()
    {        
        string nodeList = "http://localhost:9200/";

        List<Node> nodes = nodeList.Split(',').Select(uri => new Node(new Uri(uri))).ToList();

        IConnectionPool sniffingConnectionPool = new SniffingConnectionPool(nodes);

        IConnectionSettingsValues connectionSettings = new ConnectionSettings(sniffingConnectionPool);

        return (T)(IElasticClient)new ElasticClient(connectionSettings);        
    }
}

公共接口ISearchWorker { void DeleteIndex(字符串索引名); T GetClient(); } 公共类ElasticSearchWorker:ISearchWorker { 公共void DeleteIndex(字符串索引名) { IElasticClient elasticClient=GetClient(); if(elasticClient.indexists(indexName.Exists) { _=elasticClient.DeleteIndex(indexName); } } 公共T GetClient() { 字符串节点列表=”http://localhost:9200/"; List nodes=nodeList.Split(',')。选择(uri=>newnode(newuri(uri))).ToList(); IConnectionPool sniffingConnectionPool=新的sniffingConnectionPool(节点); IConnectionSettingsValuesConnectionSettings=新连接设置(嗅探连接池); 返回(T)(IElasticClient)新ElasticClient(连接设置); } } 下面是单元测试的代码片段



    [TestClass]
    public class SearchTestClass
    {
        private ISearchWorker searchWorker;

        private Mock<ISearchWorker> searchWorkerMoq;

        private readonly string indexName = "testIndex";

        [TestInitialize]
        public void SetupElasticClient()
        {
            searchWorkerMoq = new Mock<ISearchWorker>();

            var elasticClient = new Mock<IElasticClient>();

            searchWorkerMoq.Setup(c => c.GetClient<IElasticClient>()).Returns(elasticClient.Object).Verifiable();

            searchWorker = searchWorkerMoq.Object;
        }

        [TestMethod]
        public void DeleteIndexTest()
        {
            try
            {
                searchWorker.DeleteIndex(indexName);

                searchWorkerMoq.Verify(c => c.GetClient<IElasticClient>(), Times.Once()); 
            }
            catch (System.Exception)
            {
                throw;
            }
        }
    }


[测试类]
公共类SearchTestClass
{
私人搜索工作者;
私有模拟searchWorkerMoq;
私有只读字符串indexName=“testIndex”;
[测试初始化]
public void SetupElasticClient()
{
searchWorkerMoq=newmock();
var elasticClient=new Mock();
searchWorkerMoq.Setup(c=>c.GetClient()).Returns(elasticClient.Object).Verifiable();
searchWorker=searchWorkerMoq.Object;
}
[测试方法]
public void DeleteIndexTest()
{
尝试
{
searchWorker.DeleteIndex(indexName);
searchWorkerMoq.Verify(c=>c.GetClient(),Times.Once());
}
捕获(系统异常)
{
投掷;
}
}
}
线路


searchWorkerMoq.Verify(c => c.GetClient<IElasticClient>(), Times.Once());


searchWorkerMoq.Verify(c=>c.GetClient(),Times.Once());
引发以下异常

(Moq.MockException: '
Expected invocation on the mock once, but was 0 times: c => c.GetClient<IElasticClient>())

(Moq.MockException:'
应在模拟上调用一次,但调用次数为0次:c=>c.GetClient()
通过阅读大多数Moq相关信息,似乎这不是执行Moq测试的适当方式,应在ElasticSearchWorker类外部提供IElasticClient对象

不从外部注入提供IElasticClient对象的原因是,我们计划为另一个搜索提供程序(Azure search)实现ISearchWorker,因此希望将客户端实体封装在实现ISearchWorker接口的类中


想知道是否有更好的方法来执行此测试,以及我们如何实现此场景的代码覆盖率。

因此我假设您理解为什么这不起作用,并且您只是要求“一个好方法”来修复此问题

现在我并不是说这是最好的方法,但在保持“干净”的同时,这可能是最快的方法

应用界面分离(“I”与固体)。制作两个接口,而不是一个,然后在稍后阶段实现这两个接口

// Don't have a C# IDE with me, so sorry if I leave some syntax errors. 
public interface ISearchClientProvider
{
    T GetClient<T>();
}

public interface ISearchWorker
{
    void DeleteIndex(string indexName);
}

public class ElasticSearchWorker : ISearchWorker{

    private readonly ISearchClientProvider _clientProvider;

    public ElasticSearchWorker(ISearchClientProvider clientProvider){
        _clientProvider = clientProvider;
    }

    public void DeleteIndex(string indexName)
    {
        var elasticClient = _clientProvider.GetClient<IElasticClient>();

        if (elasticClient.IndexExists(indexName).Exists)
        {
            _ = elasticClient.DeleteIndex(indexName);
        }
    }
}

public class ElasticSearchClientProvider : ISearchClientProvider{/*some implementation*/}
public class AzureSearchWorker : ISearchWorker{/*some implementation*/}
public class AzureSearchClientProvider : ISearchClientProvider{/*some implementation*/}
//我身上没有C#IDE,如果我留下一些语法错误,那么很抱歉。
公共接口ISearchClientProvider
{
T GetClient();
}
公共接口ISearchWorker
{
void DeleteIndex(字符串索引名);
}
公共类ElasticSearchWorker:ISearchWorker{
私有只读ISearchClientProvider\u clientProvider;
公共ElasticSearchWorker(ISearchClientProvider clientProvider){
_clientProvider=clientProvider;
}
公共void DeleteIndex(字符串索引名)
{
var elasticClient=_clientProvider.GetClient();
if(elasticClient.indexists(indexName.Exists)
{
_=elasticClient.DeleteIndex(indexName);
}
}
}
公共类ElasticSearchClientProvider:ISearchClientProvider{/*某些实现*/}
公共类AzureSearchWorker:ISearchWorker{/*一些实现*/}
公共类AzureSearchClientProvider:ISearchClientProvider{/*某些实现*/}
那么测试代码应该是这样的:

// would actually prefer to name it ElasticSearchWorkerTests
[TestClass]
    public class SearchTestClass
    {
        private readonly ElasticSearchWorker _searchWorker;
        private readonly ISearchClientProvider _elasticClientProvider;

        private readonly string indexName = "testIndex";

        // would prefer to name it SetupElasticSearchWorker
        [TestInitialize]
        public void SetupElasticClient()
        {
            var elasticClient = new Mock<IElasticClient>();
            // Setup for IElasticClient.IndexExists() function:
            // I don't know what is the return type of IndexExists, 
            // so I am assuming here that it is some dynamic Object
            elasticClient.Setup(c => c.IndexExists(indexName)).Returns(new {Exists = true});
            // Setup for IElasticCleint.DeleteIndex might also be necessary here.

            _elasticClientProvider = new Mock<ISearchClientProvider>();
            _elasticClientProvider.Setup(c => c.GetClient<IElasticClient>()).Returns(elasticClient.Object).Verifiable();

            _searchWorker = new ElasticSearchWorker(_elasticClientProvider);
        }

        // would prefer to name it DeleteIndexTest_GetsSearchClient, 
        // because the function does more than is checked here, e.g., Checks index, deletes index.
        [TestMethod]
        public void DeleteIndexTest()
        {
            try
            {
                searchWorker.DeleteIndex(indexName);

                searchWorkerMoq.Verify(c => c.GetClient<IElasticClient>(), Times.Once()); 
            }
            catch (System.Exception)
            {
                throw;
            }
        }
    }
//实际上更愿意将其命名为ElasticSearchWorkerTests
[测试类]
公共类SearchTestClass
{
私有只读ElasticSearchWorker\u searchWorker;
私有只读ISearchClientProvider\u elasticClientProvider;
私有只读字符串indexName=“testIndex”;
//更愿意将其命名为SetupElasticSearchWorker
[测试初始化]
public void SetupElasticClient()
{
var elasticClient=new Mock();
//IElasticClient.IndexExists()函数的设置:
//我不知道IndexExists的返回类型是什么,
//所以我在这里假设它是一个动态物体
Setup(c=>c.IndexExists(indexName)).Returns(new{Exists=true});
//此处可能还需要设置IElasticCleint.DeleteIndex。
_elasticClientProvider=新建模拟();
_elasticClientProvider.Setup(c=>c.GetClient()).Returns(elasticClient.Object).Verifiable();
_searchWorker=新的ElasticSearchWorker(_elasticClientProvider);
}
//更愿意将其命名为DeleteIndexTest_GetsSearchClient,
//因为该函数所做的工作比这里检查的要多,例如,检查索引、删除索引。
[测试方法]
public void DeleteIndexTest()
{
尝试
{
searchWorker.DeleteIndex(indexName);
searchWorkerMoq.Verify(c=>c.GetClient(),Times.Once());
}
捕获(系统异常)
{
投掷;
}
}
}
这样,在这种情况下将不会有http请求