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

时间:2015-07-09 14:27:15

标签: c# unit-testing asynchronous mvvm moq

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

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

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

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属性。

这是我目前的(非工作)测试:

[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>的{​​{1}},告诉autoDetect.DetectSpectrometerAsync(progressReporter)报告进度为10,然后确保IProgress<T>进入AutoDetectionProgress也是10。

但是,此代码有两个问题:

  1. 它不编译。 viewModel行有一个错误:autoDetectMock.Setup。我在其他(非同步)测试中使用了相同的技术来获取对传递值的访问。
  2. 这种方法是否有效?如果我对异步的理解是正确的,那么在调用Error 1 Delegate 'System.Action' does not take 1 arguments之前,调用await viewModel.AutoDetectSpectrometer();将等待调用完成,这不会产生任何影响,因为progressReporter.Report(10);调用已经返回。 / LI>

1 个答案:

答案 0 :(得分:1)

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

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

您也没有从安装程序返回任务,因此也会失败。你需要返回一个任务。

我相信,在你解决了这两件事后,它应该有用。