ver una ultima sola salientes registro plus moto llamadas llamada entrantes como claro celular borrar c# unit-testing nunit moq sequential

c# - una - llamadas entrantes y salientes



El uso de Moq para verificar las llamadas se realiza en el orden correcto (6)

Escribí un método de extensión que hará valer según el orden de invocación.

public static class MockExtensions { public static void ExpectsInOrder<T>(this Mock<T> mock, params Expression<Action<T>>[] expressions) where T : class { // All closures have the same instance of sharedCallCount var sharedCallCount = 0; for (var i = 0; i < expressions.Length; i++) { // Each closure has it''s own instance of expectedCallCount var expectedCallCount = i; mock.Setup(expressions[i]).Callback( () => { Assert.AreEqual(expectedCallCount, sharedCallCount); sharedCallCount++; }); } } }

Funciona al aprovechar la forma en que funcionan los cierres con respecto a las variables de ámbito. Como solo hay una declaración para sharedCallCount, todos los cierres tendrán una referencia a la misma variable. Con expectedCallCount, una instancia nueva se instancia cada iteración del ciclo (en lugar de simplemente usar i en el cierre). De esta forma, cada cierre tiene una copia de mi alcance solo para compararlo con sharedCallCount cuando se invocan las expresiones.

Aquí hay una prueba de unidad pequeña para la extensión. Tenga en cuenta que este método se llama en su sección de configuración, no en su sección de afirmación.

[TestFixture] public class MockExtensionsTest { [TestCase] { // Setup var mock = new Mock<IAmAnInterface>(); mock.ExpectsInOrder( x => x.MyMethod("1"), x => x.MyMethod("2")); // Fake the object being called in order mock.Object.MyMethod("1"); mock.Object.MyMethod("2"); } [TestCase] { // Setup var mock = new Mock<IAmAnInterface>(); mock.ExpectsInOrder( x => x.MyMethod("1"), x => x.MyMethod("2")); // Fake the object being called out of order Assert.Throws<AssertionException>(() => mock.Object.MyMethod("2")); } } public interface IAmAnInterface { void MyMethod(string param); }

Necesito probar el siguiente método:

CreateOutput(IWriter writer) { writer.Write(type); writer.Write(id); writer.Write(sender); // many more Write()s... }

Creé un Moq''d IWriter y quiero asegurarme de que los métodos Write() se IWriter en el orden correcto.

Tengo el siguiente código de prueba:

var mockWriter = new Mock<IWriter>(MockBehavior.Strict); var sequence = new MockSequence(); mockWriter.InSequence(sequence).Setup(x => x.Write(expectedType)); mockWriter.InSequence(sequence).Setup(x => x.Write(expectedId)); mockWriter.InSequence(sequence).Setup(x => x.Write(expectedSender));

Sin embargo, la segunda llamada a Write() en CreateOutput() (para escribir el valor de id ) MockException una MockException con el mensaje " IWriter.Write () la invocación falló con el comportamiento simulado estricto. Todas las invocaciones en el simulacro deben tener una configuración correspondiente. ".

También me resulta difícil encontrar documentación / ejemplos definitivos y actualizados de las secuencias de Moq.

¿Estoy haciendo algo mal o no puedo configurar una secuencia con el mismo método? Si no, ¿hay alguna alternativa que pueda usar (preferiblemente usando Moq / NUnit)?


Hay un error al usar MockSequence en el mismo simulacro . Definitivamente se solucionará en versiones posteriores de la biblioteca Moq (también se puede arreglar manualmente al cambiar la implementación de Moq.MethodCall.Matches).

Si desea utilizar solo Moq, puede verificar el orden de las llamadas a través de callbacks:

int callOrder = 0; writerMock.Setup(x => x.Write(expectedType)).Callback(() => Assert.That(callOrder++, Is.EqualTo(0))); writerMock.Setup(x => x.Write(expectedId)).Callback(() => Assert.That(callOrder++, Is.EqualTo(1))); writerMock.Setup(x => x.Write(expectedSender)).Callback(() => Assert.That(callOrder++, Is.EqualTo(2)));


La solución más simple sería usar una Queue :

var expectedParameters = new Queue<string>(new[]{expectedType,expectedId,expectedSender}); mockWriter.Setup(x => x.Write(expectedType)) .Callback((string s) => Assert.AreEqual(expectedParameters.Dequeue(), s));


Logré obtener el comportamiento que deseo, pero requiere descargar una biblioteca de terceros de http://dpwhelan.com/blog/software-development/moq-sequences/

La secuencia puede luego probarse usando lo siguiente:

var mockWriter = new Mock<IWriter>(MockBehavior.Strict); using (Sequence.Create()) { mockWriter.Setup(x => x.Write(expectedType)).InSequence(); mockWriter.Setup(x => x.Write(expectedId)).InSequence(); mockWriter.Setup(x => x.Write(expectedSender)).InSequence(); }

Agregué esto como una respuesta en parte para ayudar a documentar esta solución, pero todavía estoy interesado en si se puede lograr algo similar usando solo Moq 4.0.

No estoy seguro de si Moq todavía está en desarrollo, pero sería bueno ver si soluciona el problema con MockSequence o incluye la extensión moq-sequences en Moq.


Recientemente, armé dos funciones para Moq: VerifyInSequence () y VerifyNotInSequence (). Funcionan incluso con Loose Mocks. Sin embargo, estos solo están disponibles en una bifurcación de repositorio moq:

https://github.com/grzesiek-galezowski/moq4

y aguarden más comentarios y pruebas antes de decidir si se pueden incluir en la versión oficial de moq. Sin embargo, nada le impide descargar la fuente como ZIP, compilarla en un dll y probarla. Usando estas características, la verificación de secuencia que necesita podría escribirse como tal:

var mockWriter = new Mock<IWriter>() { CallSequence = new LooseSequence() }; //perform the necessary calls mockWriter.VerifyInSequence(x => x.Write(expectedType)); mockWriter.VerifyInSequence(x => x.Write(expectedId)); mockWriter.VerifyInSequence(x => x.Write(expectedSender));

(Tenga en cuenta que puede usar otras dos secuencias, dependiendo de sus necesidades. La secuencia suelta permitirá cualquier llamada entre las que desea verificar. StrictSequence no permitirá esto y StrictAnytimeSequence es como StrictSequence (no hay llamadas de método entre llamadas verificadas), pero permite la secuencia a ser precedida por cualquier cantidad de llamadas arbitrarias.

Si decide probar esta función experimental, por favor coméntela con sus pensamientos en: https://github.com/Moq/moq4/issues/21

¡Gracias!


Sospecho que lo esperado no es lo que esperas.

Sin embargo, probablemente solo escribiría mi propia implementación de IWriter para verificar en este caso ... probablemente sea mucho más fácil (y más fácil de cambiar más adelante).

Perdón por ningún consejo de Moq directamente. Me encanta, pero no he hecho esto en eso.

¿Quizás necesites agregar .Verify () al final de cada configuración? (Eso realmente es una suposición aunque tengo miedo).