O.O*_*O.O 6 c# unit-testing asynchronous mvvm-light .net-4.5.2
由于没有RelayCommandAsync(至少不是我所知道的),如何测试这种情况.例如:
public RelayCommand LoadJobCommand
{
get
{
return this.loadJobCommand ?? (
this.loadJobCommand =
new RelayCommand(
this.ExecuteLoadJobCommandAsync));
}
}
private async void ExecuteLoadJobCommandAsync()
{
await GetData(...);
}
Run Code Online (Sandbox Code Playgroud)
测试:
vm.LoadJobCommand.Execute()
Assert.IsTrue(vm.Jobs.Count > 0)
Run Code Online (Sandbox Code Playgroud)
这实际上取决于您要测试的内容:
RelayCommand正确连接并调用您的async
方法?或者
Async方法逻辑是否正确?1.a 使用外部依赖来验证
根据我个人的经验,测试触发器是否正确连接以执行命令,然后测试您的类是否已按预期与另一个外部类交互的最简单方法。例如
private async void ExecuteLoadJobCommandAsync()
{
await GetData(...);
}
private async void GetData(...)
{
var data = await _repo.GetData();
Jobs.Add(data);
}
Run Code Online (Sandbox Code Playgroud)
测试您的存储库是否被调用相当容易。
public void TestUsingExternalDependency()
{
_repo.Setup(r => r.GetData())
.Returns(Task.Run(() => 5))
.Verifiable();
_vm.LoadJobCommand.Execute(null);
_repo.VerifyAll();
}
Run Code Online (Sandbox Code Playgroud)
我有时甚至这样做,这样它就不会尝试处理所有内容:
[Test]
public void TestUsingExternalDependency()
{
_repo.Setup(r => r.GetData())
.Returns(() => { throw new Exception("TEST"); })
.Verifiable();
try
{
_vm.LoadJobCommand.Execute(null);
}
catch (Exception e)
{
e.Message.Should().Be("TEST");
}
_repo.VerifyAll();
}
Run Code Online (Sandbox Code Playgroud)
1.b 使用调度程序
另一种选择是使用调度程序,并使用它来安排任务。
public interface IScheduler
{
void Execute(Action action);
}
// Injected when not under test
public class ThreadPoolScheduler : IScheduler
{
public void Execute(Action action)
{
Task.Run(action);
}
}
// Used for testing
public class ImmediateScheduler : IScheduler
{
public void Execute(Action action)
{
action();
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的 ViewModel 中
public ViewModelUnderTest(IRepository repo, IScheduler scheduler)
{
_repo = repo;
_scheduler = scheduler;
LoadJobCommand = new RelayCommand(ExecuteLoadJobCommandAsync);
}
private void ExecuteLoadJobCommandAsync()
{
_scheduler.Execute(GetData);
}
private void GetData()
{
var a = _repo.GetData().Result;
Jobs.Add(a);
}
Run Code Online (Sandbox Code Playgroud)
还有你的测试
[Test]
public void TestUsingScheduler()
{
_repo.Setup(r => r.GetData()).Returns(Task.Run(() => 2));
_vm = new ViewModelUnderTest(_repo.Object, new ImmediateScheduler());
_vm.LoadJobCommand.Execute(null);
_vm.Jobs.Should().NotBeEmpty();
}
Run Code Online (Sandbox Code Playgroud)
GetData逻辑如果您想测试GetData()逻辑甚至ExecuteLoadJobCommandAsync()逻辑。然后,您绝对应该将要测试的方法设置为Internal,并将您的程序集标记为,InternalsVisibleTo以便您可以直接从测试类调用这些方法。