我需要为一大堆C#代码编写一些测试,类似于下面的例子。这是我在C#中的第一个任务之一,我已经不幸被直接转入异步代码:(。它是一个提出大量数据库请求的Web应用程序:
namespace Foo.ViewModel
{
public class FooViewModel
{
private ManagementService _managementService;
public int Status { get; set; }
public Foo()
{
Status = 5;
_managementService = new ManagementService();
_managementService.GetCustomerInfoCompleted += new EventHandler<GetCustomerInfoEventArgs>(CustomerInfoCallback);
}
public void GetCustomerInfo(int count)
{
int b;
if (someCondition() || otherCondition())
{
b = 2;
}
else
{
b = SomeOtherAsynchronousMethod();
}
_managementService.GetCustomerInfoAsync(b, count);
//when completed will call CustomerInfoCallback
}
void CustomerInfoCallback(object sender, GetCustomerInfoEventArgs args)
{
Status = args.Result.Result.Total;
UpdateView();
}
}
}
我希望能够像这样运行一个简单的测试:
[TestMethod]
public void TestExecute5()
{
Foo f = new Foo();
f.GetCustomerInfo(5);
Assert.AreEqual(10, f.Status);
}
但显然用不同的方法并不那么简单。
ManagementService中可能有40个异步方法,由~15个不同的ViewModel调用 - 这个ViewModel调用大约8个异步方法。异步调用是通过基于事件的异步模式实现的,因此我们没有任何漂亮的异步&#39;或等待&#39;等待&#39;功能
如何让测试以某种方式工作,我可以调用GetCustomerInfo方法并在回调完成后检查状态,我该怎么办?
答案 0 :(得分:1)
如果您要测试是否触发了某个事件,则需要一种方法来进入事件处理程序。由于您使用integration-testsing
标记了问题,因此我假设您要测试服务和视图模型是否正常工作。如果允许依赖注入到视图模型中,则可以构造如下内容:
public class ViewModel
{
private readonly ManagementService _managementService;
public ViewModel(ManagementService service)
{
_managementService = service;
}
public void DoSomething()
{
_managementService.DoWork();
}
}
public class ManagementService
{
public event EventHandler SomethingHappened;
public void DoWork()
{
System.Threading.Thread.Sleep(2000);
if (SomethingHappened != null)
SomethingHappened(this, null);
}
}
然后,当您去测试视图模型和服务时,您可以执行以下操作:
[TestMethod, Timeout(5000)]
public void TestMethod1()
{
var testManagementService = new ManagementService();
AutoResetEvent evt = new AutoResetEvent(false);
testManagementService.SomethingHappened += delegate (System.Object o, System.EventArgs e)
{
evt.Set();
};
var vm = new ViewModel(testManagementService);
evt.WaitOne();
}