Como você zombar corretamente um IEnumerable <T>?

votos
6

Meu último desastre tropeço através de zombaria não é grokking que eu preciso realmente empurrar resultados dentro de um objeto fictício de IEnumerable<T>.

Aqui está um exemplo (demonstração apenas IEnumerable<T>, não realmente bom teste baseado em interação!):

using System;
using System.Collections.Generic;
using Rhino.Mocks;
using MbUnit.Framework;

[TestFixture]
public class ZooTest
{
    [Test]
    public void ZooCagesAnimals()
    {
        MockRepository mockery = new MockRepository();

        IZoo zoo = new Zoo();

        // This is the part that feels wrong to create.
        IList<IAnimal> mockResults = mockery.DynamicMock<IList<IAnimal>>();
        IAnimal mockLion = mockery.DynamicMock<IAnimal>();
        IAnimal mockRhino = mockery.DynamicMock<IAnimal>();

        using (mockery.Record())
        {
            Expect.Call(zoo.Animals)
                .Return(mockResults)
                .Repeat.Once();
        }

        using (mockery.Playback())
        {
            zoo.CageThe(mockLion);
            zoo.CageThe(mockRhino);

            Assert.AreEqual(mockResults, new List<IAnimal>(zoo.Animals));
        }       
    }
}


public class Zoo : IZoo
{
    private IList<IAnimal> animals = new List<IAnimal>();

    public void CageThe(IAnimal animal)
    {
        animals.Add(animal);
    }

    public IEnumerable<IAnimal> Animals
    {
        get
        {
            foreach(IAnimal animal in animals)
            {
                yield return animal;
            }
        }
    }
}

public interface IAnimal
{
}

public interface IZoo
{
    IEnumerable<IAnimal> Animals { get;}
    void CageThe(IAnimal animal);
}

Eu não gosto de como eu tenho que trabalhar, pelas seguintes razões:

  • Consumir os IEnumerable<IAnimal>resultados em IList<IAnimal>- porque eu entendo isso coloca os resultados para verificar para a pilha.
  • Configurando o conteúdo dos resultados - que eu entendo bem; mas o meu ponto principal é para testar se Zoo.Animalsestá retornando IEnumerable<IAnimal>, e ainda melhor, que ele está usando yield returnpara dentro.

Todas as sugestões sobre como fazer isso melhor ou mais simples?

Edit: Eu estou tentando determinar a melhor maneira de testar a interação entre IEnumerable<T>e tudo o que eu estou usando. Eu não estou tentando testar que Zoopode segurar os animais, mas sim que Zooexpõe como IEnumerable<IAnimal>, e que yield returnestá sendo usado também.

Publicado 07/08/2008 em 06:58
fonte usuário
Em outras línguas...                            


2 respostas

votos
4

Se você está testando a implementação , por que você está tentando zombar-lo em primeiro lugar? Porque não basta CageThe (IAnimal) e depois verificar que os animais contém o IAnimal?

Eu entendo que você está zombando das IAnimals, vendo como aparentemente você ainda não tem nenhum animais concretas para brincar, mas por que não apenas torná-los canhotos, porque, obviamente, você não está esperando alguma coisa acontecer com eles além de ser colocar na lista?

Edit: Algo mais ou menos ao longo destas linhas (não testado, pode não compilar, pode comer o seu cão etc.):

[TestFixture]
public class ZooTest 
{
    [Test]
    public void ZooCagesAnimals()
    {
        MockRepository mockery = new MockRepository();

        IAnimal mockLion = mockery.Stub<IAnimal>();
        IAnimal mockRhino = mockery.Stub<IAnimal>();

        IZoo zoo = new Zoo();

        zoo.CageThe(mockLion);
        zoo.CageThe(mockRhino);

        List<IAnimal> animals = new List<IAnimal>(zoo.Animals);
        Assert.IsTrue(animals.Contains(mockLion));
        Assert.IsTrue(animals.Contains(mockRhino));
    }
}
Respondeu 07/08/2008 em 07:20
fonte usuário

votos
3

Eu não vejo como você espera criar expectativas simulados em um objeto que não é um mock para começar. Além disso, você está definindo-se a expectativa de retornar um IList que não é realmente o que acontece quando o compilador gera um iterador.

Se você quiser testar especificamente o iterador, você provavelmente deve

Assert.IsNotNull(zoo.Animals);

E, em seguida, verificar se o recenseador realmente enumera sobre todas as coisas que você adicionou ao Zoo. Que é o que eu estava indo para lá. :)

Eu não tenho certeza se é mesmo possível testar se o retorno de rendimento está sendo chamado, porque o rendimento de retorno é apenas um açúcar sintático para um IEnumerable gerado pelo compilador. Por exemplo, chamando

zoo.Animals.GetEnumerator();

não irá executar qualquer código que você escreveu no recenseador. A primeira vez que isso acontece é na primeira chamada para IEnumerator.MoveNext ();

Agora, se você está tentando testar a interação entre o Jardim Zoológico de concreto eo IEnumerable contido por esse Zoo, você deve fazer o IEnumerable um campo em Zoo e injetar um IEnumerable simulada a esse campo em vez de implementar um concreto IEnumerable diretamente no Zoo.

Espero que este seja de alguma ajuda.

Respondeu 08/08/2008 em 06:27
fonte usuário

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