测试调用 BackgroundWorker 的方法
Testing a method that calls a BackgroundWorker
描述
考虑如下 class。它有一个 BackgroundWorker
作为一个 属性,以及一个让它报告进度的方法:
public class MyClass
{
protected BackgroundWorker _worker;
public MyClass(BackgroundWorker worker)
{
_worker = worker;
}
public void ReportProgress(int percentage)
{
_worker.ReportProgress(percentage);
}
}
问题
ReportProgress()
应该检测吗?
如果以上问题的答案是“是”?怎么办?已尝试使用 FakeItEasy 进行以下测试:
[Test]
public void ReportProgress_Test()
{
// arrange
var fakeWorker = A.Fake<System.ComponentModel.BackgroundWorker>();
fakeWorker.WorkerReportsProgress = true;
MyClass underTest = new MyClass(fakeWorker);
// act
underTest.ReportProgress(percentage);
// assert
A.CallTo(() => fakeWorker.ReportProgress(percentage)).MustHaveHappened();
}
此测试产生以下错误:
Message: FakeItEasy.Configuration.FakeConfigurationException :
The current proxy generator can not intercept the method System.ComponentModel.BackgroundWorker.ReportProgress(System.Int32 percentProgress) for the following reason:
- Non-virtual members can not be intercepted. Only interface members and virtual, overriding, and abstract members can be intercepted.
一种选择是引入一个界面,如评论中所述。如果后台工作人员的唯一用途是报告进度,这可能是个好主意。
但并非所有测试都需要对所有依赖项使用 Mocks,在许多情况下使用真实的具体对象也可以。这将导致测试同时测试两个对象以及它们之间的交互。在某些情况下,这将是有益的,因为它会捕获不正确的用法,在其他情况下,您可能希望单独测试它们以降低复杂性。我不认为一种方法适用于所有情况。
在这种情况下应该相当简单,只要调用 ReportProgress
就应该引发 ProgressChanged
事件。因此,只需将事件处理程序附加到事件并检查它是否提供预期结果。 IE。像这样。
public void TestProgress()
{
var bw = new BackgroundWorker();
int progress = 0;
bw.ProgressChanged += (o, e) => progress = e.ProgressPercentage;
var underTest = new MyClass(bw);
underTest.ReportProgress(42);
Assert.AreEqual(progress, 42);
}
“是否应该测试报告进度”的问题是基于情况和意见的。我认为测试 one-line 方法的价值相当低,但如果是更大系统的一部分,进度报告可能对测试很有价值。
描述
考虑如下 class。它有一个 BackgroundWorker
作为一个 属性,以及一个让它报告进度的方法:
public class MyClass
{
protected BackgroundWorker _worker;
public MyClass(BackgroundWorker worker)
{
_worker = worker;
}
public void ReportProgress(int percentage)
{
_worker.ReportProgress(percentage);
}
}
问题
ReportProgress()
应该检测吗?
如果以上问题的答案是“是”?怎么办?已尝试使用 FakeItEasy 进行以下测试:
[Test]
public void ReportProgress_Test()
{
// arrange
var fakeWorker = A.Fake<System.ComponentModel.BackgroundWorker>();
fakeWorker.WorkerReportsProgress = true;
MyClass underTest = new MyClass(fakeWorker);
// act
underTest.ReportProgress(percentage);
// assert
A.CallTo(() => fakeWorker.ReportProgress(percentage)).MustHaveHappened();
}
此测试产生以下错误:
Message: FakeItEasy.Configuration.FakeConfigurationException :
The current proxy generator can not intercept the method System.ComponentModel.BackgroundWorker.ReportProgress(System.Int32 percentProgress) for the following reason:
- Non-virtual members can not be intercepted. Only interface members and virtual, overriding, and abstract members can be intercepted.
一种选择是引入一个界面,如评论中所述。如果后台工作人员的唯一用途是报告进度,这可能是个好主意。
但并非所有测试都需要对所有依赖项使用 Mocks,在许多情况下使用真实的具体对象也可以。这将导致测试同时测试两个对象以及它们之间的交互。在某些情况下,这将是有益的,因为它会捕获不正确的用法,在其他情况下,您可能希望单独测试它们以降低复杂性。我不认为一种方法适用于所有情况。
在这种情况下应该相当简单,只要调用 ReportProgress
就应该引发 ProgressChanged
事件。因此,只需将事件处理程序附加到事件并检查它是否提供预期结果。 IE。像这样。
public void TestProgress()
{
var bw = new BackgroundWorker();
int progress = 0;
bw.ProgressChanged += (o, e) => progress = e.ProgressPercentage;
var underTest = new MyClass(bw);
underTest.ReportProgress(42);
Assert.AreEqual(progress, 42);
}
“是否应该测试报告进度”的问题是基于情况和意见的。我认为测试 one-line 方法的价值相当低,但如果是更大系统的一部分,进度报告可能对测试很有价值。