Como a zombar IGetMappingResponse de ElasticSearch ninho para Testes Unitários

votos
3

Eu e minhas faculdades têm construído um módulo de acesso a dados que faz operações CRUD e busca para um banco de dados ElasticeSearch (6.2.0) NoSQL. Estamos usando NEST (6.2.0), um cliente de alto nível para mapear para o DSL consulta ElasticSearch. O módulo foi codificado em C #, em uma biblioteca de classe em um quadro alvo .NET Standard 2.0.

Em alguns métodos é necessário para recuperar o mapeamento do índice dos índices armazenados em ElasticSearch para que as informações de campo, como os tipos de campos e propriedades de texto pode ser usado para construir consultas de pesquisa no banco de dados ElasticSearch. Somos capazes de fazer isso usando o método GetMapping do Nest (retorna Nest.IGetMappingResponse).

Nós não estamos tendo problemas de execução de código. Tudo funciona bem. No entanto, quando vamos para construir um teste de unidade para métodos que utiliza o método GetMapping, não somos capazes de mock up a resposta ele retorna (IGetMappingResponse). Eu originalmente usado FakeItEasy a fingir, e depois inserido alguns dos dados que eu precisava no objeto. No entanto, para explicar o meu problema um pouco melhor, eu criei uma classe que implementa IGetMappingResponse para zombar minha resposta. O problema surge quando eu tento criar uma instância de TypeMappings para a propriedade Mapeamento de IndexMapping (Em troca é para Índices de propriedade para o simulado). Eu recebo um erro dizendo “não 'TypMappings' não contém um construtor que leva 0 argumentos.

public class MockedGetMappingResponse : IGetMappingResponse
    {
        public IReadOnlyDictionary<IndexName, IndexMappings> Indices
        {
            get
            {
                return new ReadOnlyDictionary<Nest.IndexName, Nest.IndexMappings>(new Dictionary<Nest.IndexName, Nest.IndexMappings>
                {
                    [statuses] = new IndexMappings
                    {
                        Mappings = new TypeMappings() //Error happens here!!
                    }                      

                });
            }
            set { }
        }

        public IReadOnlyDictionary<IndexName, IndexMappings> Mappings
        {
            get
            {
                return null;
            }
            set { }
        }

        public void Accept(IMappingVisitor visitor)
        {
            // Just a test
        }

        public bool IsValid
        {
            get
            {
                return true;
            }
        }

        public ServerError ServerError
        {
            get
            {
                return null;
            }
        }

        public Exception OriginalException
        {
            get
            {
                return null;
            }
        }

        public string DebugInformation
        {
            get
            {
                return ;
            }
        }

        public IApiCallDetails ApiCall
        {
            get
            {
                return null;
            }
            set
            {
                //do nothing
            }
        }

        public bool TryGetServerErrorReason(out string reason)
        {
            reason = ;
            return false;
        }
    }      

}

Quando eu procurar as definições para o tipo de ninho TypeMappings Eu não vejo um construtor construído. Portanto, presumo que ele deve estar usando o padrão, um construtor sem argumentos. Mas, aparentemente, isso não acontece. Eu preciso saber como ir sobre zombando TypeMappings em IGetMappingResponse. Se não há nenhuma maneira de criar uma instância de TypeMappings, eu preciso saber como criar um IGetMappingResponse zombou à minha resposta esperada para que eu possa testar meu código.

Publicado 27/11/2018 em 17:59
fonte usuário
Em outras línguas...                            


1 respostas

votos
1

Com a ajuda de Nkosi descobri que TypeMappings tem um construtor interno. Sabendo disso, eu criei uma instância de TypeMappings usando a reflexão. Aqui está o código que usei para criar o objeto.

IReadOnlyDictionary<TypeName, TypeMapping> backingDictionary = new ReadOnlyDictionary<TypeName, TypeMapping>(new Dictionary<TypeName, TypeMapping>
        {
            [typeName.Name] = typeMapping

        });           

        Type[] typeMappingsArgs = new Type[] { typeof(IConnectionConfigurationValues), typeof(IReadOnlyDictionary<TypeName, TypeMapping>) };
        object[] typeMappingsInputParams = new object[] { elasticClient.ConnectionSettings, backingDictionary };
        TypeMappings typeMappings = (TypeMappings)typeof(TypeMappings).GetConstructor(
              BindingFlags.NonPublic | BindingFlags.Instance,
              null, typeMappingsArgs, null).Invoke(typeMappingsInputParams);

Aqui está o código para criar o meu IGetMappingResponse zombou. Eu costumava FakeItEasy para inserir algumas informações.

private Nest.IGetMappingResponse GetFakeMappingResponse(Nest.IElasticClient elasticClient)
    {
        var fieldName = "fieldName";
        var indexName = "indexName";
        var documentTypeName = "documentTypeName";

        var typeMapping = new TypeMapping();
        var properties = new Properties();
        typeMapping.Properties = properties;

        var property = new TextProperty();
        property.Name = fieldName;            

        PropertyName propertyName = new PropertyName(fieldName);

        typeMapping.Properties.Add(propertyName, property);

        Type[] typeNameArgs = new Type[] { typeof(string) };
        object[] typeNameInputParams = new object[] { documentTypeName };
        TypeName typeName = (TypeName)typeof(TypeName).GetConstructor(
              BindingFlags.NonPublic | BindingFlags.Instance,
              null, typeNameArgs, null).Invoke(typeNameInputParams);


        IReadOnlyDictionary<TypeName, TypeMapping> backingDictionary = new ReadOnlyDictionary<TypeName, TypeMapping>(new Dictionary<TypeName, TypeMapping>
        {
            [typeName.Name] = typeMapping

        });           

        Type[] typeMappingsArgs = new Type[] { typeof(IConnectionConfigurationValues), typeof(IReadOnlyDictionary<TypeName, TypeMapping>) };
        object[] typeMappingsInputParams = new object[] { elasticClient.ConnectionSettings, backingDictionary };
        TypeMappings typeMappings = (TypeMappings)typeof(TypeMappings).GetConstructor(
              BindingFlags.NonPublic | BindingFlags.Instance,
              null, typeMappingsArgs, null).Invoke(typeMappingsInputParams);

        IndexMappings indexMappings = new IndexMappings();
        typeof(IndexMappings).GetProperty("Mappings", BindingFlags.Public | BindingFlags.Instance).SetValue(indexMappings, typeMappings);

        ReadOnlyDictionary<Nest.IndexName, Nest.IndexMappings> indices = new ReadOnlyDictionary<Nest.IndexName, Nest.IndexMappings>(new Dictionary<Nest.IndexName, Nest.IndexMappings>
        {
            [indexName] = indexMappings

        });

        var fakeMappingResponse = A.Fake<IGetMappingResponse>();
        A.CallTo(() => fakeMappingResponse.ServerError).Returns(null);
        A.CallTo(() => fakeMappingResponse.IsValid).Returns(true);
        A.CallTo(() => fakeMappingResponse.Indices).Returns(indices);

        return fakeMappingResponse;
    }
Respondeu 28/11/2018 em 17:37
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more