验证从异步调用报告的进度是否在单元测试中正确报告
Verifying progress reported from an async call is properly report in unit tests
我正在编写一些代码,可以自动检测设备(在本例中为光谱仪)连接到的串行端口。
我有自动检测部分,我正在尝试为显示检测进度、错误等的 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);
}
我想做的是获取传递给autoDetect.DetectSpectrometerAsync(progressReporter)
的IProgress<T>
,告诉IProgress<T>
报告进度10,然后确保AutoDetectionProgress
在 viewModel
中也是 10。
但是,这段代码有两个问题:
- 它不编译。
autoDetectMock.Setup
行有一个错误:Error 1 Delegate 'System.Action' does not take 1 arguments
。我在其他(非同步)测试中使用了相同的技术来访问传递的值。
- 这种方法行得通吗?如果我对异步的理解是正确的,调用
await viewModel.AutoDetectSpectrometer();
将在调用 progressReporter.Report(10);
之前等待调用完成,这不会有任何效果,因为 AutoDetectSpectrometer()
调用已经返回。
您必须为回调指定return类型;编译器将无法为您确定这一点。
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; });
您也没有return从您的设置中执行任务,因此也会失败。您需要 return 一项任务。
我相信,在你解决了这两个问题之后,它应该会起作用。
我正在编写一些代码,可以自动检测设备(在本例中为光谱仪)连接到的串行端口。
我有自动检测部分,我正在尝试为显示检测进度、错误等的 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);
}
我想做的是获取传递给autoDetect.DetectSpectrometerAsync(progressReporter)
的IProgress<T>
,告诉IProgress<T>
报告进度10,然后确保AutoDetectionProgress
在 viewModel
中也是 10。
但是,这段代码有两个问题:
- 它不编译。
autoDetectMock.Setup
行有一个错误:Error 1 Delegate 'System.Action' does not take 1 arguments
。我在其他(非同步)测试中使用了相同的技术来访问传递的值。 - 这种方法行得通吗?如果我对异步的理解是正确的,调用
await viewModel.AutoDetectSpectrometer();
将在调用progressReporter.Report(10);
之前等待调用完成,这不会有任何效果,因为AutoDetectSpectrometer()
调用已经返回。
您必须为回调指定return类型;编译器将无法为您确定这一点。
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; });
您也没有return从您的设置中执行任务,因此也会失败。您需要 return 一项任务。
我相信,在你解决了这两个问题之后,它应该会起作用。