如何模拟具有参数的异步保护方法?
How can I mock an async protected method that has a parameter?
这是我要测试的class:
namespace ClassLibrary1
{
public class MyBase
{
public async Task DoSomething (MyContext context) => await DoSomethingInternal (context);
public async Task DoSomething() => await DoSomethingInternal();
protected virtual async Task DoSomethingInternal(MyContext context) { }
protected virtual async Task DoSomethingInternal() { }
}
public class MyContext { }
public class MyClass : MyBase
{
protected override Task DoSomethingInternal(MyContext context) => Task.CompletedTask;
protected override Task DoSomethingInternal() => Task.CompletedTask;
}
}
这是测试代码:
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[ExpectedException(typeof(TaskCanceledException))]
public async Task TestMethod1()
{
var mock = new Mock<MyClass>
{
CallBase = true
};
mock.Protected().Setup<Task>("DoSomethingInternal", new MyContext()).ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething(null);
}
[TestMethod]
[ExpectedException(typeof(TaskCanceledException))]
public async Task TestMethod2()
{
var mock = new Mock<MyClass>
{
CallBase = true
};
mock.Protected().Setup<Task>("DoSomethingInternal").ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething();
}
}
}
结果显示第一次测试失败,第二次成功。调试显示第一个测试调用 DoSomethingInternal(context)
returns Task.CompletedTask
,而不是抛出异常。
那么我怎样才能让它抛出呢?
设置中传递的参数与执行测试时传递的实例不匹配。在这种情况下,您将需要使用参数匹配器以允许代码按预期流动。
Setting expectations for protected members, if you need argument matching, you MUST use ItExpr
rather than It
var mock = new Mock<MyClass>() {
CallBase = true
};
mock.Protected()
.Setup<Task>("DoSomethingInternal", ItExpr.IsAny<MyContext>())
.ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething(null);
这是我要测试的class:
namespace ClassLibrary1
{
public class MyBase
{
public async Task DoSomething (MyContext context) => await DoSomethingInternal (context);
public async Task DoSomething() => await DoSomethingInternal();
protected virtual async Task DoSomethingInternal(MyContext context) { }
protected virtual async Task DoSomethingInternal() { }
}
public class MyContext { }
public class MyClass : MyBase
{
protected override Task DoSomethingInternal(MyContext context) => Task.CompletedTask;
protected override Task DoSomethingInternal() => Task.CompletedTask;
}
}
这是测试代码:
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[ExpectedException(typeof(TaskCanceledException))]
public async Task TestMethod1()
{
var mock = new Mock<MyClass>
{
CallBase = true
};
mock.Protected().Setup<Task>("DoSomethingInternal", new MyContext()).ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething(null);
}
[TestMethod]
[ExpectedException(typeof(TaskCanceledException))]
public async Task TestMethod2()
{
var mock = new Mock<MyClass>
{
CallBase = true
};
mock.Protected().Setup<Task>("DoSomethingInternal").ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething();
}
}
}
结果显示第一次测试失败,第二次成功。调试显示第一个测试调用 DoSomethingInternal(context)
returns Task.CompletedTask
,而不是抛出异常。
那么我怎样才能让它抛出呢?
设置中传递的参数与执行测试时传递的实例不匹配。在这种情况下,您将需要使用参数匹配器以允许代码按预期流动。
Setting expectations for protected members, if you need argument matching, you MUST use
ItExpr
rather thanIt
var mock = new Mock<MyClass>() {
CallBase = true
};
mock.Protected()
.Setup<Task>("DoSomethingInternal", ItExpr.IsAny<MyContext>())
.ThrowsAsync(new TaskCanceledException());
var obj = mock.Object;
await obj.DoSomething(null);