簡體   English   中英

帶有約束的Moq表達式…It.Is <Expression<Func<T, bool> &gt;&gt;

[英]Moq Expression with Constraint … It.Is<Expression<Func<T, bool>>>

好的,我很難解決如何為采用表達式的方法設置最小起訂量的問題。 有很多關於如何實現它的示例。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();

如果我將設置更改為It.IsAny ...,它將起作用,並在“返回”方法中返回預期的對象設置。

我已經找到了一些有關如何在Web上執行此操作的示例,一個示例是這樣做的,另一個示例是使用編譯的,但是我也無法使它正常工作。 如何使它適用於特定的表達式?

根據答案更新工作解決方案


@ carlos-alejo讓我朝正確的方向前進,或者至少讓我踢回了“編譯”操作。 我在想錯了。 我現在基於使用編譯的解決方案。 了解編譯的關鍵是為它提供一個對象,通過該對象可以評估/生成表達式。

因此,在我的情況下,如果有人給我這樣的表達:

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”的表達式

也許只是我沒有在這點上串連,但希望它能對其他人有所幫助。

似乎這里真正的問題是,如您在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());
}

請注意,使用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());

也許對羽毛開發者會有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM