En el siguiente ejemplo de código, tengo una clase de calculadora Async. Esto se inyecta con un ICalc, que será una calculadora sincrónica. Utilizo la inyección de la dependencia y me burlo del ICalc porque esto se parece a mi verdadero escenario, aunque supongo que la burla no es realmente relevante para la pregunta. El AsyncCalc tiene una función que llamará a otra función de forma asíncrona, tomando una devolución de llamada como parámetro. Y cuando finaliza la llamada a la función asincrónica, la devolución de llamada se activará con el resultado.Prueba de la unidad función asíncrona
Ahora quiero probar mi función asíncrona, comprobando que la devolución de llamada se desencadena con el parámetro esperado. Este código parece funcionar. Sin embargo, creo que podría explotar en cualquier momento, y mi preocupación es que la condición de carrera de la devolución de llamada finalice antes de que la función finalice y la prueba finalice, ya que esto se ejecutará en un hilo separado.
Mi pregunta ahora es si estoy en la unidad de pista correcta probando la función asíncrona, o si alguien puede ayudarme a seguir el camino correcto ...? Lo que se sentiría mejor es si pudiera garantizar que la devolución de llamada se desencadene de inmediato, ¿y preferiblemente en el mismo hilo, supongo? ¿Se puede/debe hacerse?
public interface ICalc
{
int AddNumbers(int a, int b);
}
public class AsyncCalc
{
private readonly ICalc _calc;
public delegate void ResultProcessor(int result);
public delegate int AddNumbersAsyncCaller(int a, int b);
public AsyncCalc(ICalc calc)
{
_calc = calc;
}
public void AddNumbers(int a, int b, ResultProcessor resultProcessor)
{
var caller = new AddNumbersAsyncCaller(_calc.AddNumbers);
caller.BeginInvoke(a, b, new AsyncCallback(AddNumbersCallbackMethod), resultProcessor);
}
public void AddNumbersCallbackMethod(IAsyncResult ar)
{
var result = (AsyncResult)ar;
var caller = (AddNumbersAsyncCaller)result.AsyncDelegate;
var resultFromAdd = caller.EndInvoke(ar);
var resultProcessor = ar.AsyncState as ResultProcessor;
if (resultProcessor == null) return;
resultProcessor(resultFromAdd);
}
}
[Test]
public void TestingAsyncCalc()
{
var mocks = new MockRepository();
var fakeCalc = mocks.DynamicMock<ICalc>();
using (mocks.Record())
{
fakeCalc.AddNumbers(1, 2);
LastCall.Return(3);
}
var asyncCalc = new AsyncCalc(fakeCalc);
asyncCalc.AddNumbers(1, 2, TestResultProcessor);
}
public void TestResultProcessor(int result)
{
Assert.AreEqual(3, result);
}
yo creo que la prueba simplemente tendría que esperar en un bucle hasta que la devolución de llamada se ejecuta. –