我该如何模拟一个带有参数的异步受保护方法?

4

这是我的测试类:

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) 的调用返回 Task.CompletedTask,而不是抛出异常。
那么我该如何让它抛出异常呢?
1个回答

5

在测试执行时传递的实例与设置中传递的参数不匹配。在这种情况下,您需要使用参数匹配器,以使代码按预期流动。

如果您需要参数匹配,请使用 ItExpr 而不是 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);

参考 Moq 快速入门:杂项


非常好,非常感谢。 - Nico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接