调用函数的设置方法

时间:2017-03-14 08:30:22

标签: c# unit-testing moq mstest

我的类中有一个方法,它接收一个函数(Func)作为参数:

T Execute<T>(Func<T> func)
{
    ...
    return func();
}

我希望模拟这个类,让Moq调用我发送给Execute的函数作为参数。

我如何致电Execute

string result = await executor.Execute(async () => await GetResponse(query));

所以我希望Moq调用GetResponse并返回其值。我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

我不完全确定这个问题包含所有信息,因为它非常简单:

    public interface I
    {
      T Execute<T>(Func<T> func);
    }

    [TestMethod]
    public void TestMethod1()
    {
      var mock = new Mock<I>();
      mock.Setup(x => x.Execute<string>(It.IsAny<Func<string>>())).Returns((Func<string> x) => x());

      Func<string> myFunc = () => "test";

      Assert.AreEqual("test", mock.Object.Execute(myFunc));
    }

答案 1 :(得分:1)

首先,如果代码本身已编入您的代码中,则无法模拟它。模拟GetResponse只有在它是某个外部组件时才有意义。否则,它属于你的班级,不应该嘲笑,但应该在单元测试中进行测试。

要模拟它,请将此代码重构为与此类似。

public class Executor
{
    // IResponseProvider has the GetResponse method.
    // This interface can be mocked in test and can be injected in real environment.
    public IResponseProvider ResponseProvider { get; set; }

    public async Task<T> Execute<T>(Func<T> func)
    {
        var response = await ResponseProvider.GetResponse(query);
        // do something with response...
        return func();
    }
}

现在您可以测试 Executor类及其Execute方法,您可以模拟外部IResponseProvider成员在测试环境中做一些事情:

[TestFixture] // MSTest: [TestClass]
public class ExecutorTest
{
    private Executor executor;
    private Mock<IResponseProvider> responseProviderMock;

    [SetUp] // MSTest: [TestInitialize]
    public void Init()
    {
        // this is not a mock but the class to be tested
        executor = new Executor();

        // the external components can be mocked, though:
        responseProviderMock = new Mock<IResponseProvider>();

        // setup the mock:
        executor.ResponseProvider = responseProviderMock.Object;
        Func<string> mockResponse = () => "dummy mocked response";
        responseProviderMock.Setup(m => m.GetResponse(It.IsAny<MyQueryType>))
            .Returns(Task.FromResult(mockResponse));
    }

    [Test] // MSTest: [TestMethod]
    public async Task ExecuteSuccessTest()
    {
         // Arrange
         Func<int> input = () => 42;

         // Act
         var result = executor.Execute(input);

         // Assert
         Assert.AreEqual(42, result);
         responseProviderMock.Verify(rp => rp.GetResponse(It.IsAny<MyQueryType>(), Times.Once);
    }
}