带约束的 Moq 表达式 ... It.Is<Expression<Func<T, bool>>>
Moq Expression with Constraint ... It.Is<Expression<Func<T, bool>>>
好的,我很难弄清楚如何为采用表达式的方法设置最小起订量。有很多关于如何 It.IsAny<>... 的示例,这不是我想要的。我在做约束之后,所以 It.Is<>。我已经设置了它,但它从未 return 达到我要求它 return 的值。
// 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... 它会起作用并且 return 是 "returns" 方法中的预期对象设置。
我在网上找到了几个如何执行此操作的示例,一个是这样做的,另一个是使用编译,但我也无法使其工作。您如何使它适用于特定表达式?
根据答案更新工作解决方案
@carlos-alejo 让我朝着正确的方向前进,或者至少让我回到了编译操作。我想错了。我现在有基于使用编译的解决方案。关于 compile 要理解的关键是你给它一个对象,通过它 evaluate/generate 表达式。
所以在我的情况下,如果有人给我这样的表达:
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" } };
然后我可以像这样创建我的 "setup" 调用:
this.bindingManager.Setup(c => c.GetUserBinding(It.Is<Expression<Func<UserBinding, bool>>>(y => y.Compile()(testBinding))))
.Returns(new List<UserBinding>() { testBinding }.AsQueryable());
这有效,在我的情况下,return让我返回测试绑定对象,因为我已设置。如果将 testBinding 更改为 (注意我更改了用户名):
var testBinding = new UserBinding { Binding = new Binding { Name = "Default binding" }, Domain = "test.com", User = new User() { Username = "Testing Framework2" } };
它不会工作,因为我的被测系统中的代码会生成一个表达式来寻找 "Test Framework"
也许只是我没有把这些点联系起来,但希望它能帮助其他人。
这里真正的问题似乎是如何比较两个 lambda 表达式,正如您在 It.Is<Expression<Func<UserBinding, bool>>> (criteria => criteria == testExpression)
子句中尝试做的那样。使用@neleus 的 answer to 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
进行比较,则测试失败。
当我在寻找模拟 Where() 和过滤一些数据的方法时,
在被测代码中看起来像:
Repository<Customer>().Where(x=>x.IsActive).ToList()
我可以根据其他人的回答设计这样的例子:
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());
也许对羽毛开发者有帮助。
好的,我很难弄清楚如何为采用表达式的方法设置最小起订量。有很多关于如何 It.IsAny<>... 的示例,这不是我想要的。我在做约束之后,所以 It.Is<>。我已经设置了它,但它从未 return 达到我要求它 return 的值。
// 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... 它会起作用并且 return 是 "returns" 方法中的预期对象设置。
我在网上找到了几个如何执行此操作的示例,一个是这样做的,另一个是使用编译,但我也无法使其工作。您如何使它适用于特定表达式?
根据答案更新工作解决方案
@carlos-alejo 让我朝着正确的方向前进,或者至少让我回到了编译操作。我想错了。我现在有基于使用编译的解决方案。关于 compile 要理解的关键是你给它一个对象,通过它 evaluate/generate 表达式。
所以在我的情况下,如果有人给我这样的表达:
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" } };
然后我可以像这样创建我的 "setup" 调用:
this.bindingManager.Setup(c => c.GetUserBinding(It.Is<Expression<Func<UserBinding, bool>>>(y => y.Compile()(testBinding))))
.Returns(new List<UserBinding>() { testBinding }.AsQueryable());
这有效,在我的情况下,return让我返回测试绑定对象,因为我已设置。如果将 testBinding 更改为 (注意我更改了用户名):
var testBinding = new UserBinding { Binding = new Binding { Name = "Default binding" }, Domain = "test.com", User = new User() { Username = "Testing Framework2" } };
它不会工作,因为我的被测系统中的代码会生成一个表达式来寻找 "Test Framework"
也许只是我没有把这些点联系起来,但希望它能帮助其他人。
这里真正的问题似乎是如何比较两个 lambda 表达式,正如您在 It.Is<Expression<Func<UserBinding, bool>>> (criteria => criteria == testExpression)
子句中尝试做的那样。使用@neleus 的 answer to 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
进行比较,则测试失败。
当我在寻找模拟 Where() 和过滤一些数据的方法时, 在被测代码中看起来像:
Repository<Customer>().Where(x=>x.IsActive).ToList()
我可以根据其他人的回答设计这样的例子:
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());
也许对羽毛开发者有帮助。