gpt4 book ai didi

c# - 单元测试异步函数

转载 作者:IT王子 更新时间:2023-10-29 04:34:53 24 4
gpt4 key购买 nike

在下面的代码示例中,我有一个异步计算器类。它注入(inject)了一个 ICalc,它将成为一个同步计算器。我使用依赖注入(inject)并模拟 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);
}

最佳答案

你可以使用 ManualResetEvent同步您的线程。

在以下示例中,测试线程将阻塞对 completion.WaitOne() 的调用。异步计算的回调存储结果,然后通过调用 completion.Set() 向事件发出信号。

[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);

var completion = new ManualResetEvent(false);
int result = 0;
asyncCalc.AddNumbers(1, 2, r => { result = r; completion.Set(); });
completion.WaitOne();

Assert.AreEqual(3, calcResult);
}

// ** USING AN ANONYMOUS METHOD INSTEAD
// public void TestResultProcessor(int result)
// {
// Assert.AreEqual(3, result);
// }

关于c# - 单元测试异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2113697/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com