2011-04-05 10 views
8

estoy usando Moq y tengo la siguiente interfaz:Cómo burlarse de una interfaz que se extiende IEnumerable

public interface IGameBoard : IEnumerable<PieceType> 
{ 
    ... 
} 
public class GameBoardNodeFactory 
{ 
    public virtual GameBoardNode Create (int row, int column, IGameBoard gameBoard) 
    { 
     ... 
    } 
} 

entonces tengo una prueba como esta:

var clonedGameBoardMock = new Mock<IGameBoard> (MockBehavior.Loose); 
var gameBoardNodeFactoryMock = new Mock<GameBoardNodeFactory>(); 
gameBoardNodeFactoryMock.Setup (x => 
    x.Create (
     position.Row, 
     position.Column, 
     clonedGameBoardMock.Object)).Returns (new GameBoardNode { Row = position.Row, Column = position.Column }); 

Pero entonces gameBoardNodeFactoryMock.Object .Create (position.Row, position.Column, clonedGameBoardMock.Object) arroja una NullReferenceException. Traté de crear un simulacro para el IGameBoard de manera que no extienda la interfaz IEnumerable <PieceType> y luego funcione.

Cualquier ayuda es apreciada.

Respuesta

0

Bien, si alguien está interesado, actualicé Moq a la versión 4 y ahora todo funciona como se esperaba.

0

Una referencia nula en esta situación generalmente significa que su instalación nunca se cumplió. Lo que significa que nunca fue llamado con los valores exactos para los que lo configuró. Para depurar esto, haría que tu coincidencia sea menos restrictiva al usar It.IsAny() y así sucesivamente para asegurarte de que la prueba coincidirá con cualquier llamada a la función de burla. En la mayoría de los casos esto es lo suficientemente bueno. ¿Alguna razón por la que intentas concordar en valores específicos?

10

Debería crear una configuración para GetEnumerator() si se está llamando. Algo así como:

var mockPieces = new List<PieceType>; 
clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(mockPieces.GetEnumerator()); 

Nota seguro de si esa es la cuestión en este caso, pero vale la pena destacar si alguna vez tiene que burlarse IEnumerable<T>.

3

The answer by @DanBryant también fue la clave de nuestra solución. Sin embargo, el enumerador en ese caso podría ser reutilizado accidentalmente. En su lugar, se sugiere emplear:

clonedGameBoardMock.Setup(g => g.GetEnumerator()).Returns(() => mockPieces.GetEnumerator()); 

Aquí hay una repro completa (nueva biblioteca de clases utilizando NUnit 2.6.4 y Moq 4.2):

public interface IMyThing<T> : IEnumerable<T> 
{ 
    string Name { get; set; } 

    IMyThing<T> GetSub<U>(U key); 
} 

public interface IGenericThing 
{ 
    string Value { get; set; } 
} 

public class Pet 
{ 
    public string AnimalName { get; set; } 
} 

public class Unit 
{ 
    public IEnumerable<Pet> ConvertInput(IMyThing<IGenericThing> input) 
    { 
     return input.GetSub("api-key-123").Select(x => new Pet { AnimalName = x.Value }); 
    } 
} 

[TestFixture] 
public class Class1 
{ 
    [Test] 
    public void Test1() 
    { 
     var unit = new Unit(); 
     Mock<IMyThing<IGenericThing>> mock = new Mock<IMyThing<IGenericThing>>(); 
     Mock<IMyThing<IGenericThing>> submock = new Mock<IMyThing<IGenericThing>>(); 

     var things = new List<IGenericThing>(new[] { new Mock<IGenericThing>().Object }); 

     submock.Setup(g => g.GetEnumerator()).Returns(() => things.GetEnumerator()); 
     mock.Setup(x => x.GetSub(It.IsAny<string>())).Returns(submock.Object); 

     var result = unit.ConvertInput(mock.Object); 
     Assert.That(result, Is.Not.Null.And.Not.Empty); 
     Assert.That(result, Is.Not.Null.And.Not.Empty); // This would crash if the enumerator wasn't returned through a Func<>... 
    } 
} 

Por si sirve de algo/de hacer esta pregunta pop hasta ese único Google-Googler con el mismo problema que tuve: lo anterior es una versión resumida de la interfaz IView<T> del cliente Couchbase .NET, que también implementa IEnumerable<T>.

Cuestiones relacionadas