c# unit-testing asynchronous async-await nsubstitute

c# - NSubstitute-async-no se espera la llamada



unit-testing asynchronous (2)

Siempre que el predicado Received() se vuelva demasiado complicado o simplemente no coincida con NSubstitute, siempre puede capturar las args especificadas utilizando callbacks a través de When().Do() o .AndDoes() . Para su caso de uso que sería algo como esto

DatabaseParams receivedParms = null; databaseHelperSub.ExecuteProcAsync(Arg.Any<DatabaseParams>()) .Returns(Task.FromResult((object)null)) .AndDoes(x => receivedParms = x.Arg<DatabaseParams>); //Act await underTest.ExecuteAsync(request); //Assert receivedParms.Should().NotBeNull(); // assert your parms...

Estoy intentando verificar que se haya llamado a un método asíncrono con los parámetros correctos. Sin embargo, recibo la advertencia:

"Debido a que no se espera esta llamada, la ejecución del método actual continúa antes de que se complete la llamada. Considere la posibilidad de aplicar el operador ''esperar'' al resultado de la llamada". Esta advertencia aparece en la línea de código debajo del //Assert Comentario de //Assert (a continuación).

Mi prueba con NSubstitute es la siguiente:

[Test] public async Task SimpleTests() { //Arrange var request = CreateUpdateItemRequest(); databaseHelperSub.ExecuteProcAsync(Arg.Any<DatabaseParams>()).Returns(Task.FromResult((object)null)); //Act await underTest.ExecuteAsync(request); //Assert databaseHelperSub.Received().ExecuteProcAsync(Arg.Is<DatabaseParams>( p => p.StoredProcName == StoredProcedureName && p.Parameters[0].ParameterName == "Param1" && p.Parameters[0].Value.ToString() == "Value1" && p.Parameters[1].ParameterName == "Param2" && p.Parameters[1].Value.ToString() == "Value2")); }

La unidad bajo el método de prueba underTest.ExecuteAsync(request) llama a ExecuteProcedureAsync y realiza la espera:

var ds = await DatabaseHelper.ExecuteProcAsync(dbParams);

Debido al hecho de que con NSubstitute, se requiere Received () después de la ejecución de la unidad bajo prueba. Mientras que en RhinoMocks, puede esperar que ocurra una llamada antes de que se ejecute la unidad bajo prueba. RhinoMocks puede devolver Task.FromResult () mientras que NSubstitute no puede.

El equivalente de RhinoMocks que funciona es este:

[Test] public async Task SimpleTest() { // Arrange var request = new UpdateItemRequest(); databaseHelperMock.Expect(m => m.ExecuteProcAsync(Arg<DatabaseParams>.Matches( p => p.StoredProcName == StoredProcedureName && p.Parameters[0].ParameterName == "Param1" && p.Parameters[0].Value.ToString() == "Value1" && p.Parameters[1].ParameterName == "Param2" && p.Parameters[1].Value.ToString() == "Value2 ))).Return(Task.FromResult<object>(null)); // Act await underTest.ExecuteAsync(request); }

He visto que hay una solución alternativa en la que puede agregar un método de extensión para eliminar el problema:

public static class TestHelper { public static void IgnoreAwait(this Task task) { } }

Lo que significa que mi línea de prueba para NSubstitute se puede ejecutar de la siguiente manera y la advertencia desaparece:

databaseHelperSub.Received().ExecuteProcAsync(Arg.Is<DatabaseParams>( p => p.StoredProcName == StoredProcedureName && p.Parameters[0].ParameterName == "Param1" && p.Parameters[0].Value.ToString() == "Value1" && p.Parameters[1].ParameterName == "Param2" && p.Parameters[1].Value.ToString() == "Value2")).IgnoreAwait(); }

Sin embargo, asumí que debe haber una mejor solución para esto.


Tan pronto como actualice a la versión 1.9.0 o superior, podrá usar el modo await sin recibir una NullReferenceException .