今天在测试中需要用 Mock 对下面的接口进行 mock
public interface IMarkdownClient
{
Task<string> RenderAsync(string text, MarkdownRenderOption opt, bool allowFallback = true, CancellationToken cancellationToken = default(CancellationToken));
}
尝试用下面的代码进行 mock
markdownClient.Setup(x => x.RenderAsync(It.IsAny<string>(), It.IsAny<MarkdownRenderOption>()))
却报错
CS0854 - An expression tree may not contain a call or invocation that uses optional arguments.
通过 Comparing mocking frameworks: How to handle optional parameter with NSubstituite, Moq and FakeItEasy 知道了,Moq 不支持可选参数,必须要给可选参数传值
var markdownClient = new Mock<IMarkdownClient>();
markdownClient.Setup(x => x.RenderAsync(
It.IsAny<string>(),
It.IsAny<MarkdownRenderOption>(),
It.IsAny<bool>(),
It.IsAny<CancellationToken>()));
原因是
This is not actually an issue with the mocking frameworks but rather the underlying expression tree API that doesn't support optional arguments
直接返回传入的 text 参数值,通过下面的代码解决了
ReturnsAsync<string, MarkdownRenderOption, bool, CancellationToken, IMarkdownClient, string>((x, y, z, _) => x)
其中第1-4个类型是 RenderAsync
方法的4个参数类型,IMarkdownClient
是所 mock 的接口,最后一个 string
是方法返回值的类型
完整代码如下:
var markdownClient = new Mock<IMarkdownClient>();
markdownClient.Setup(x => x.RenderAsync(
It.IsAny<string>(),
It.IsAny<MarkdownRenderOption>(),
It.IsAny<bool>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync<string, MarkdownRenderOption, bool, CancellationToken, IMarkdownClient, string>((x, y, z, _) => x);