lambda表达式中的替换方法

时间:2014-08-27 20:51:36

标签: c# lambda delegates

我正在为单个接口上定义的一系列类似方法编写单元测试(这是重构的前提)。我发现类似的代码出现在多种方法中:

// Each line here shows up in a different test method.
mock.Setup(m => m.MethodA()).Returns(() => true);
mock.Setup(m => m.MethodB()).Returns(() => true);
mock.Setup(m => m.MethodC()).Returns(() => true);

我想创建一个单一的方法,我可以传递给要测试的方法,但不知道如何做到这一点。我想要一些看起来像这样的东西:

// testMethod is some method defined on IMyInterface.
private Mock<IMyInterface> SetupMockObject(Func<bool> testMethod)
{
    var mock = new Mock<MyInterface>();
    mock.Setup(m => m.testMethod()).Returns(() => true);
    return mock;
}

对此方法的调用将类似于:

var configuredMockObject = SetupMockObject(MethodA);

这可能吗?

编辑:表达式树似乎是我需要的 - 以前我没有得到你可以传递lambda表达式的概念。我已经粘贴了下面的解决方案,因为我花了一点时间来解决这个问题,尽管dBurner和Servy的答案都证明是有帮助的。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Language.Flow;
using System;
using System.Linq.Expressions;

namespace ExampleTest
{
    [TestClass]
    public class TestClass
    {
        private Mock<IMyInterface> _mock;

        private interface IMyInterface
        {
            bool MethodA();
            bool MethodB();
        }

        private ISetup<IMyInterface, bool> SetupMockObject(Expression<Func<IMyInterface,bool>> lambda)
        {
            var mockSetup = _mock.Setup(lambda);
            return mockSetup;
        }

        [TestInitialize]
        public void Setup()
        {
            _mock = new Mock<IMyInterface>();
        }

        [TestMethod]
        public void TestMethodA()
        {
            SetupMockObject(i => i.MethodA()).Returns(true);     
            // Proceed with act and assert.
        }

        [TestMethod]
        public void TestMethodB()
        {
            SetupMockObject(i => i.MethodB()).Returns(true);
            // Proceed with act and assert.
        }
    }
}

2 个答案:

答案 0 :(得分:2)

传递给它的lambda需要有一个mocked类型的参数,而你当前的参数接受一个无参数的委托:

public static Mock<MyInterface> SetupMockObject<T>(
    Func<MyInterface, bool> testMethod)
{
    var mock = new Mock<MyInterface>();
    mock.Setup(testMethod).Returns(() => true);
    return mock;
}

这允许你写:

var mock = SetupMockObject(m => m.MethodA());

并让代码等同于

var mock = new Mock<MyInterface>();
mock.Setup(m => m.MethodA()).Returns(() => true);

答案 1 :(得分:1)

您可以使用表达式树。您的CommonTest方法应该有一个Expression<Func<bool>>参数。

使用此参数类型,您可以获取方法名称。在此之后,您应该构建另一个表示m => m.MethodFromParameter的表达式。