c# - 验证从异步调用报告的进度是否在单元测试中正确报告

标签 c# unit-testing asynchronous mvvm moq

我正在研究一些可以自动检测设备(在本例中为光谱仪)连接到的串行端口的代码。

我有自动检测部分工作,我正在尝试为 ViewModel 编写测试,以显示检测、错误等的进度。

这是执行实际检测的代码的接口(interface)。

public interface IAutoDetector
{
  Task DetectSpectrometerAsync(IProgress<int> progress);
  bool IsConnected { get; set; }
  string SelectedSerialPort { get; set; }
}

这是使用 IAutoDetector 的 ViewModel检测光谱仪
public class AutoDetectViewModel : Screen
{
   private IAutoDetector autoDetect;
   private int autoDetectionProgress;

   public int AutoDetectionProgress
   {
      get { return autoDetectionProgress; }
      private set
      {
         autoDetectionProgress = value;
         NotifyOfPropertyChange();
      }
   }

   [ImportingConstructor]
   public AutoDetectViewModel(IAutoDetector autoDetect)
   {
      this.autoDetect = autoDetect;
   }

   public async Task AutoDetectSpectrometer()
   {
      Progress<int> progressReporter = new Progress<int>(ProgressReported);
      await autoDetect.DetectSpectrometerAsync(progressReporter);
   }

   private void ProgressReported(int progress)
   {
      AutoDetectionProgress = progress;
   }
}

我正在尝试编写一个测试来验证 IAutoDetector 报告的进度。更新 AutoDetectionProgress AutoDetectionViewModel 中的属性(property).

这是我当前的(非工作)测试:
[TestMethod]
public async Task DetectingSpectrometerUpdatesTheProgress()
{
   Mock<IAutoDetector> autoDetectMock = new Mock<IAutoDetector>();
   AutoDetectViewModel viewModel = new AutoDetectViewModel(autoDetectMock.Object);

   IProgress<int> progressReporter = null;
   autoDetectMock.Setup(s => s.DetectSpectrometerAsync(It.IsAny<IProgress<int>>()))
      .Callback((prog) => { progressReporter = prog; });

   await viewModel.AutoDetectSpectrometer();
   progressReporter.Report(10);
   Assert.AreEqual(10, viewModel.AutoDetectionProgress);
}

我想做的是捕获IProgress<T>传递给 autoDetect.DetectSpectrometerAsync(progressReporter) ,告诉IProgress<T>报告进度为 10,然后确保 AutoDetectionProgressviewModel也是10。

然而,这段代码有两个问题:
  • 它不编译。 autoDetectMock.Setup行有错误:Error 1 Delegate 'System.Action' does not take 1 arguments .我在其他(非同步)测试中使用了相同的技术来访问传递的值。
  • 这种方法甚至会奏效吗?如果我对异步的理解是正确的,调用 await viewModel.AutoDetectSpectrometer();在调用 progressReporter.Report(10); 之前将等待调用完成,这不会有任何影响,因为 AutoDetectSpectrometer()电话已经返回。
  • 最佳答案

    您必须指定回调的返回类型;编译器将无法为您确定这一点。

    autoDetectMock
          .Setup(s => s.DetectSpectrometerAsync(It.IsAny<IProgress<int>>()))
          .Callback((prog) => { progressReporter = prog; }); // what you have
    

    应该
    autoDetectMock
          .Setup(s => s.DetectSpectrometerAsync(It.IsAny<IProgress<int>>()))
          .Callback<IProgress<int>>((prog) => { progressReporter = prog; }); 
    

    您也没有从设置中返回任务,因此也会失败。您需要返回一个任务。

    我相信,在你解决这两个问题之后,它应该可以工作。

    关于c# - 验证从异步调用报告的进度是否在单元测试中正确报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31320444/

    相关文章:

    c# - 从异步方法更新进度条

    python - python 单元测试中的 Neo4j 临时数据库

    unit-testing - 单元测试中的Grails Unique Id约束没有失败

    python - 通过线程+队列或ThreadPoolExecutor使用异步等待吗?

    java - Vert.x IO 阻塞操作性能

    c# - WebClient.DownloadString 给出第一次机会异常

    c# - 如何在 asp.net 中流式传输视频内容?

    java - 上传到 S3 的单元测试

    node.js - Node 7 : How to Show the Correct Stack Trace in Async Mongoose Promises

    c# - 在控制台应用程序中覆盖 txt 文件 C# 中的输出