unit-testing tdd mocking fakeiteasy

unit-testing - moq c#



Fingir un enumerador en FakeItEasy (2)

No estoy del todo seguro de que entiendo lo que quiere decir, el código que proporcionó siempre fallará. Sin embargo, si quiere decir que quiere que sea verdadero la segunda vez que se lo llama, puede hacerlo. Hay un par de formas diferentes en las que puedo pensar, dos de ellas son:

A.CallTo(() => enumerator.MoveNext()).ReturnsNextFromSequence(false, true);

La otra forma es:

A.CallTo(() => enumerator.MoveNext()).Returns(true); A.CallTo(() => enumerator.MoveNext()).Returns(false).Once();

Editar:

En segundo lugar, supongo que entiendo mejor tu pregunta, ¿qué quieres que suceda es que MoveNext debería volverse verdadero la primera vez y falso la segunda vez? Si ese es el caso, simplemente cambie las órdenes de los valores en los ejemplos anteriores.

FakeItEasy no utiliza un modelo de grabación / reproducción y tiene razón en que la última regla configurada tiene prioridad sobre las reglas especificadas anteriormente. Es por eso que debe especificar repeat - ".Once ()" - en la última configuración para que solo sea válida una vez.

Hay muchas razones por las cuales la última tiene prioridad, una de las más importantes es que le permite configurar un valor de retorno predeterminado en la configuración de su dispositivo y anularlo para devolver valores específicos en algunas de sus pruebas, esto es imposible cuando usando un modelo de grabación / reproducción.

¿Cómo puedo crear un falso con FakeItEasy que permite diferentes valores de devolución en llamadas sucesivas? Este es un ejemplo de lo que me gustaría poder hacer:

var enumerator = A.Fake<IDictionaryEnumerator>(); A.CallTo(() => enumerator.MoveNext()).Returns(true); //Expected value for first call A.CallTo(() => enumerator.Key).Returns("key1"); A.CallTo(() => enumerator.Value).Returns("value1"); A.CallTo(() => enumerator.MoveNext()).Returns(false); //Expected value for second call Assert.IsTrue(enumerator.MoveNext()); //Fails Assert.IsFalse(enumerator.MoveNext());

La aserción fallará ya que la última configuración de MoveNext sobrescribirá la primera.

¿Es posible hacer lo que quiero en FakeItEasy ?

.

[Editar]
Aclaró el ejemplo de la pregunta original y proporcionó un ejemplo de trabajo a continuación.

Según la respuesta de Patrik, este código muestra cómo puedes configurar el falso. El truco es invertir todas las configuraciones y usar Once() .

var enumerator = A.Fake<IDictionaryEnumerator>(); A.CallTo(() => enumerator.MoveNext()).Returns(false).Once(); A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(2); A.CallTo(() => enumerator.Key).Returns("key2").Once(); A.CallTo(() => enumerator.Value).Returns("value2").Once(); A.CallTo(() => enumerator.Key).Returns("key1").Once(); A.CallTo(() => enumerator.Value).Returns("value1").Once(); while(enumerator.MoveNext()) { Debug.WriteLine(enumerator.Key + ": "+ enumerator.Value); }

Esto se imprimirá:

key1: value1 key2: value2


El ejemplo de OP basado en la respuesta de Patrik está bien ... pero tedioso si la secuencia crece. Para complementar esa respuesta, considere que a pesar de que los ejemplos falsos / falsos con frecuencia muestran un montón de código de línea recta para organizarse, usted tiene la potencia total de un lenguaje de programación a su disposición. Condicionales, bucles e incluso procedimientos.

Así que considere lo siguiente:

public static void AFakeDictionaryEnumeratorReturns( IDictionaryEnumerator enumerator, params object[] pairs) { if (0 != pairs.Length % 2) throw new ArgumentException("pairs must have even number of elements", "pairs"); int n = pairs.Length / 2; A.CallTo(() => enumerator.MoveNext()).Returns(false).Once(); A.CallTo(() => enumerator.MoveNext()).Returns(true).NumberOfTimes(n); for (int i = pairs.Length; i > 0; i -= 2) { A.CallTo(() => enumerator.Key).Returns(pairs[i - 2]).Once(); A.CallTo(() => enumerator.Value).Returns(pairs[i - 1]).Once(); } }

y ahora la prueba se convierte en:

var enumerator = A.Fake<IDictionaryEnumerator>(); AFakeDictionaryEnumeratorReturns(enumerator, "key1", "value1", "key2", "value2", "key3", "value3"); var keys = new List<object>(); var values = new List<object>(); while (enumerator.MoveNext()) { keys.Add(enumerator.Key); values.Add(enumerator.Value); } Assert.Equal(new List<object> { "key1", "key2", "key3" }, keys); Assert.Equal(new List<object> { "value1", "value2", "value3" }, values);

(Un IDictionaryEnumerator trata en pares, por lo que este ejemplo no es tan claramente beneficioso como podría ser. Para un IEnumerator<T> estándar, un único método genérico estático serviría para un conjunto completo de diferentes enumeradores).