具有约束的Moq表达式... It.Is <表达式<func <t,bool =“”>&gt;&gt;

时间:2016-05-24 19:39:53

标签: c# moq

好的,我正在努力弄清楚如何为一个接受表达式的方法设置moq。有很多关于如何使用它的例子.IsAny&lt;&gt; ...这不是我所追求的。我正在做一个约束,所以It.Is&lt;&gt;。我已经设置了但它永远不会返回我要求它返回的值。

// Expression being setup
Expression<Func<UserBinding, bool>> testExpression = binding =>
binding.User.Username == "Testing Framework";


// Setup of what expression to look for. 
 this.bindingManager.Setup(
            c => c.GetUserBinding(It.Is<Expression<Func<UserBinding, bool>>>
(criteria => criteria == testExpression)))
            .Returns(new List<UserBinding>() { testBinding }.AsQueryable());

// Line of code call from within the class being tested. So this is being mocked and should return the defined object when the same lambda is passed in.
 this.bindingManager.GetUserBinding(b => b.User.Username == username)
                .SingleOrDefault();

// class under test. So for the test this is being called. 
// so this is the method being called and inside this method is where the binding manager is being mocked and called. 
var response = this.controller.SendMessage(message, true).Result;

        response.StatusCode.Should().Be(HttpStatusCode.BadRequest);

 // inside the controller.SendMessage method this method is called with the lambda expression. I have verified the usernames match but when the setup is It.Is this returns null instead of the object setup in the "setup" call. 
this.bindingManager.GetUserBinding(b => b.User.Username == username)
                .SingleOrDefault();

如果我将设置更改为It.IsAny ...它工作并返回“returns”方法中的预期对象设置。

我已经找到了一些如何在网络上执行此操作的示例,其中一个是这样做,另一个是使用编译,但我无法让它工作。你如何让这个特定表达式工作?

使用基于答案的工作解决方案进行更新

@ carlos-alejo让我朝着正确的方向前进,或者至少踢我回到Compile行动。我在想错了。我现在有基于使用编译的解决方案。理解编译的关键是你给它一个对象来评估/生成表达式。

所以在我的情况下,如果有人给我一个这样的表达式:

binding => binding.User.Username == "Testing Framework";

我需要像这样的UserBinding:

var testBinding = new UserBinding { Binding = new Binding { Name = "Default binding" }, Domain = "test.com", User = new User() { Username = "Testing Framework" } };
然后我可以像这样创建我的“设置”调用:

this.bindingManager.Setup(c => c.GetUserBinding(It.Is<Expression<Func<UserBinding, bool>>>(y => y.Compile()(testBinding))))
        .Returns(new List<UserBinding>() { testBinding }.AsQueryable());

这有效,在我的情况下,我已经设置了返回测试绑定对象。如果您将testBinding更改为(请注意我更改了用户名)

    var testBinding = new UserBinding { Binding = new Binding { Name = "Default binding" }, Domain = "test.com", User = new User() { Username = "Testing Framework2" } };

它不起作用,因为我测试的系统中的代码生成一个表达式,寻找“Test Framework”

也许只是我没有连接这个点,但希望它能帮助别人。

2 个答案:

答案 0 :(得分:5)

这里的真正问题似乎是如何比较两个lambda表达式,就像你在It.Is<Expression<Func<UserBinding, bool>>> (criteria => criteria == testExpression)子句中尝试的那样。使用@ neleus对this question的回答,我可以提出实际通过的测试:

readonly Mock<IBindingManager> bindingManager = new Mock<IBindingManager>();

[Test]
public void TestMethod()
{
    Expression<Func<string, bool>> testExpression = binding => (binding == "Testing Framework");

    bindingManager.Setup(c => c.GetUserBinding(It.Is<Expression<Func<string, bool>>>(
        criteria => LambdaCompare.Eq(criteria, testExpression)))).Returns(new List<string>());

    var oc = new OtherClass(bindingManager.Object);

    var actual = oc.Test(b => b == "Testing Framework");

    Assert.That(actual, Is.Not.Null);
    bindingManager.Verify(c => c.GetUserBinding(It.Is<Expression<Func<string, bool>>>(
        criteria => LambdaCompare.Eq(criteria, testExpression))), Times.Once());
}

请注意使用LambdaCompare.Eq静态方法来比较表达式是否相同。如果我将表达式与==甚至Equals进行比较,则测试失败。

答案 1 :(得分:0)

当我寻找模拟Where()并过滤一些数据的方法时, 在被测试的代码中看起来像:

private static string GetStringFromUser(string prompt)
{
    Console.Write(prompt);
    return Console.ReadLine();
}

private static double GetDoubleFromUser(string prompt)
{
    double input;

    // double.TryParse attempts to convert a string into a double, and
    // it returns a bool that indicates success. If it's successful,
    // then the out parameter will contain the converted value. Here
    // we loop until we get a successful result, then we return the value.
    do
    {
        Console.Write(prompt);
    } while (!double.TryParse(Console.ReadLine(), out input));

    return input;
}

public static double GetBMI(double height, double weight)
{
    return weight / Math.Pow(height, 2) * 703;
}

private static ConsoleKeyInfo GetKeyFromUser(string prompt)
{
    Console.Write(prompt);
    var key = Console.ReadKey();
    Console.WriteLine();
    return key;
}

private static void Main()
{
    string name = GetStringFromUser("Enter your name: ");
    double weight = GetDoubleFromUser("Enter your weight in pounds: ");
    double height = GetDoubleFromUser("Enter your height in inches: ");
    double bmi = GetBMI(height, weight);
    Console.WriteLine($"Thank you, {name}. Your BMI is: {bmi}");

    GetKeyFromUser("\n\nDone! Press any key to exit...");
}

我可以根据其他人的答案设计这样的示例:

Repository<Customer>().Where(x=>x.IsActive).ToList() 

也许对羽毛开发者会有帮助。