具有约束条件的Moq表达式... It.Is <Expression <Func <T,bool >>>

Tod*_*ddB 5 c# moq

好的,我很难解决如何为采用表达式的方法设置最小起订量的问题。有很多关于如何实现它的示例。IsAny <> ...这不是我所追求的。我在处理约束之后,所以是It.Is <>。我已经设置了它,但是它从不返回我要求它返回的值。

// 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();
Run Code Online (Sandbox Code Playgroud)

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

我已经找到了一些有关如何在Web上执行此操作的示例,一个示例是这样做的,另一个示例是使用编译的,但是我也无法使它正常工作。如何使它适用于特定的表达式?

根据答案更新工作解决方案


@ carlos-alejo让我朝正确的方向前进,或者至少让我踢回了“编译”操作。我在想错了。我现在基于使用编译的解决方案。了解编译的关键是为它提供一个对象,通过该对象可以评估/生成表达式。

因此,在我的情况下,如果有人给我这样的表达:

binding => binding.User.Username == "Testing Framework";
Run Code Online (Sandbox Code Playgroud)

我需要像这样的UserBinding:

var testBinding = new UserBinding { Binding = new Binding { Name = "Default binding" }, Domain = "test.com", User = new User() { Username = "Testing Framework" } };
Run Code Online (Sandbox Code Playgroud)

然后,我可以像这样创建“设置”调用:

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

这可以正常工作,在我的情况下,设置完成后,我会返回测试绑定对象。如果将testBinding更改为(注意,我更改了用户名)

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

这将无法正常工作,因为被测系统内部的代码会生成一个寻找“ Test Framework”的表达式

也许只是我没有在这点上串连,但希望它能对其他人有所帮助。

Art*_*m G 9

当我寻找模拟Where()并过滤一些数据的方法时,测试下的代码如下所示:

Repository<Customer>().Where(x=>x.IsActive).ToList() 
Run Code Online (Sandbox Code Playgroud)

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

 var inputTestDataAsNonFilteredCustomers = new List<Customer> {cust1, cust2};
 var customersRepoMock = new Mock<IBaseRepository<Customer>>();

                IQueryable<Customer> filteredResult = null;
                customersRepoMock.Setup(x => x.Where(It.IsAny<Expression<Func<Customer, bool>>>()))
                    .Callback((Expression<Func<Customer, bool>>[] expressions) =>
                    {
                        if (expressions == null || expressions.Any() == false)
                        {
                            return;
                        }
                        Func<Customer, bool> wereLambdaExpression = expressions.First().Compile();  //  x=>x.isActive is here
                        filteredResult = inputTestDataAsNonFilteredCustomers.Where(wereLambdaExpression).ToList().AsQueryable();// x=>x.isActive was applied
                    })
                   .Returns(() => filteredResult.AsQueryable());
Run Code Online (Sandbox Code Playgroud)

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

  • 这非常简单且有用。有了这个,您可以重用课堂上编写的表达式进行良好的测试。 (2认同)

Cha*_*lie 5

似乎真正的问题在于,如您在该It.Is<Expression<Func<UserBinding, bool>>> (criteria => criteria == testExpression)子句中所做的那样,如何比较两个lambda表达式。使用@neleus对这个问题的回答,我可以提出一个实际上通过的测试:

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());
}
Run Code Online (Sandbox Code Playgroud)

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