我有一个服务在单独的库中实现,并且将Func<T>
作为函数的参数。
在模拟服务时,我仍然需要运行Func<T>
。
如何为此设置模拟对象?
我创建了以下代码示例来演示该问题:
// This is the service that is in a different library and I want to mock
public interface IServiceToMock
{
T ExecuteAsync<T>(Func<T> func);
}
public class ServiceToMock : IServiceToMock
{
public T ExecuteAsync<T>(Func<T> funcToBeExecuted)
{
// does some more logic that I don't want to test
return funcToBeExecuted();
}
}
这是服务的使用者
public class ServiceConsumer
{
private readonly IServiceToMock service;
public ServiceConsumer(IServiceToMock service) => this.service = service;
public async Task Consume()
{
await service.ExecuteAsync(async () => await ConsumeInteger(1));
await service.ExecuteAsync(async () => await ConsumeString("String"));
}
// This is the method that I want to be triggered when the Consume() is called
private async Task ConsumeInteger(int number)
{
await new Task<int>(() =>
{
Console.WriteLine(number);
return number;
});
}
// This is the method that I want to be triggered when the Consume() is called
private async Task ConsumeString(string str)
{
await new Task<string>(() =>
{
Console.WriteLine(str);
return str;
});
}
}
这是我到目前为止的测试
public class TestServiceConsumer
{
public void TestMethod()
{
var moqLibraryService = new Mock<IServiceToMock>();
// How can I set up the mock to have the Console
moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<T>>())).Returns(T());
}
}
答案 0 :(得分:0)
我认为您可以这样做:
var moqLibraryService = new Mock<IServiceToMock>();
moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<int>>()))
.Returns( (Func<int> f) => f() );
moqLibraryService.Setup(ms => ms.ExecuteAsync(It.IsAny<Func<string>>()))
.Returns( (Func<string> f) => f() );
它使用Returns
的重载,它吸收了valueFunction
而不是value
。每次模拟完成后,该匿名函数(Func<int> f) => f()
都会被再次求值。这里的f
是传递给Moq的it-is-any参数。
如果您不想明确提及类型(此处为int
,string
),可能会很难执行。那将与线程Mocking generic methods in Moq without specifying T有关。