在下面的代码示例中,我有一个异步计算器类Async Calculator。它被注入了一个同步计算器ICalc。我使用的是依赖注入,并且为ICalc进行了模拟,因为这类似于我的真实场景,尽管我猜想模拟与问题无关。AsyncCalc有一个函数,该函数将异步调用另一个函数 - 以回调作为参数。当异步函数调用完成时,回调将使用结果触发。
现在我想测试我的异步函数-检查回调是否使用期望的参数触发。这段代码似乎有效。但是,我觉得它随时可能爆炸-我的担忧是回调在函数结束和测试终止之前完成的竞争条件-因为这将在单独的线程中运行。
我的问题是,我是否正在正确地对异步函数进行单元测试,或者是否有人可以帮助我走上正确的道路?更好的做法是确保立即触发回调-最好在同一线程上吗?能/应该这样做吗?
现在我想测试我的异步函数-检查回调是否使用期望的参数触发。这段代码似乎有效。但是,我觉得它随时可能爆炸-我的担忧是回调在函数结束和测试终止之前完成的竞争条件-因为这将在单独的线程中运行。
我的问题是,我是否正在正确地对异步函数进行单元测试,或者是否有人可以帮助我走上正确的道路?更好的做法是确保立即触发回调-最好在同一线程上吗?能/应该这样做吗?
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);
}