Saltar al contenido

Espere una llamada al método Async Void para la prueba unitaria

Solución:

Tú deberías evitar async void. Uso único async void para controladores de eventos. DelegateCommand es (lógicamente) un controlador de eventos, por lo que puede hacerlo así:

// Use [InternalsVisibleTo] to share internal methods with the unit test project.
internal async Task DoLookupCommandImpl(long idToLookUp)
{
  IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

  // Close the search
  IsSearchShowing = false;
}

private async void DoStuff(long idToLookUp)
{
  await DoLookupCommandImpl(idToLookup);
}

y prueba unitaria como:

[TestMethod]
public async Task TestDoStuff()
{
  //+ Arrange
  myViewModel.IsSearchShowing = true;

  // container is my Unity container and it setup in the init method.
  container.Resolve<IOrderService>().Returns(orderService);
  orderService = Substitute.For<IOrderService>();
  orderService.LookUpIdAsync(Arg.Any<long>())
              .Returns(new Task<IOrder>(() => null));

  //+ Act
  await myViewModel.DoLookupCommandImpl(0);

  //+ Assert
  myViewModel.IsSearchShowing.Should().BeFalse();
}

Mi respuesta recomendada está arriba. Pero si realmente quieres probar un async void método, puede hacerlo con mi biblioteca AsyncEx:

[TestMethod]
public void TestDoStuff()
{
  AsyncContext.Run(() =>
  {
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();
    orderService.LookUpIdAsync(Arg.Any<long>())
                .Returns(new Task<IOrder>(() => null));

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);
  });

  //+ Assert
  myViewModel.IsSearchShowing.Should().BeFalse();
}

Pero esta solución cambia el SynchronizationContext para su modelo de vista durante su vida útil.

Un async void El método es esencialmente un método de “disparar y olvidar”. No hay forma de recuperar un evento de finalización (sin un evento externo, etc.).

Si necesita realizar una prueba unitaria de esto, le recomendaría convertirlo en un async Task método en su lugar. Entonces puedes llamar Wait() en los resultados, que le notificarán cuando se complete el método.

Sin embargo, este método de prueba tal como está escrito aún no funcionaría, ya que en realidad no está probando DoStuff directamente, sino probando un DelegateCommand que lo envuelve. Debería probar este método directamente.

Descubrí una manera de hacerlo para las pruebas unitarias:

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();

    var lookupTask = Task<IOrder>.Factory.StartNew(() =>
                                  {
                                      return new Order();
                                  });

    orderService.LookUpIdAsync(Arg.Any<long>()).Returns(lookupTask);

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);
    lookupTask.Wait();

    //+ Assert
    myViewModel.IsSearchShowing.Should().BeFalse();
}

La clave aquí es que, debido a que estoy realizando pruebas unitarias, puedo sustituir en la tarea que quiero que vuelva mi llamada asíncrona (dentro de mi vacío asíncrono). Luego, solo me aseguro de que la tarea se haya completado antes de continuar.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *