簡體   English   中英

模擬具有復雜Lambda表達式作為參數的對象

[英]Mocking objects with complex Lambda Expressions as parameters

我在嘗試模擬某些在我的項目中接收復雜的Lambda表達式的對象時遇到此問題。 通常與帶有接收此類委托的代理對象一起使用:

Func<Tobj, Fun<TParam1, TParam2, TResult>>

我曾嘗試使用Moq和RhinoMocks來模擬這些類型的對象,但是都失敗了。

這是我要做的事情的簡化示例:首先,我有一個進行計算的Calculator對象:

public class Calculator
{
     public int Add(int x, int y)
     {
          var result = x + y;
          return result;
     }  

     public int Substract(int x, int y)
     {
           var result = x - y;
           return result;
     }
}

接下來,我需要驗證Calculator類中每個方法的參數,因此為了遵循“單一職責”原則,我創建了一個驗證器類。 我使用Proxy類將所有內容連接起來,以防止重復代碼:

public class CalculatorProxy : CalculatorExample.ICalculatorProxy
{
    private ILimitsValidator _validator;

    public CalculatorProxy(Calculator _calc, ILimitsValidator _validator)
    {
        this.Calculator = _calc;
        this._validator = _validator;
    }

    public int Operation(Func<Calculator, Func<int, int, int>> operation, 
                         int x, 
                         int y)
    {
        _validator.ValidateArgs(x, y);

        var calcMethod = operation(this.Calculator);

        var result = calcMethod(x, y);

        _validator.ValidateResult(result);

        return result;
     }

     public Calculator Calculator { get; private set; }
 }

最后,我正在測試一個確實使用CalculatorProxy的組件,所以我想模擬它,例如使用Rhino Mocks:

[TestMethod]
public void ParserWorksWithCalcultaroProxy()
{

    var calculatorProxyMock = MockRepository.GenerateMock<ICalculatorProxy>();

    calculatorProxyMock.Expect(x => x.Calculator).Return(_calculator);

    calculatorProxyMock.Expect(x => x.Operation(c => c.Add, 2, 2)).Return(4);

    var mathParser = new MathParser(calculatorProxyMock);

    mathParser.ProcessExpression("2 + 2");

    calculatorProxyMock.VerifyAllExpectations();
 }

但是我無法使它正常工作! Moq因NotSupportedException而失敗,在RhinoMocks simpy中,它永遠無法滿足期望。

我已經找到了一種使用Moq解決此問題的方法:

    [TestMethod]
    public void ParserWorksWithCalcultaroProxy()
    {
        var calculatorProxyMock = new Mock<ICalculatorProxy>();
        Func<Calculator, Func<int, int, int>> addMock = c => c.Add;

        calculatorProxyMock.Setup(x => x.BinaryOperation(It.Is<Func<Calculator, Func<int, int, int>>>(m => m(_calculator) == addMock(_calculator)), 2, 2))
                                  .Returns(4).Verifiable();           

        var mathParser = new MathParser(calculatorProxyMock.Object);

        mathParser.ProcessExpression("2 + 2");

        calculatorProxyMock.Verify();
    }

通過這種方式,我可以測試通過計算器對象上的計算器代理調用的是哪種方法,從而驗證MathParser是否可以解析表達式。

我認為我將能夠將其轉化為我的真實項目。

此外,我發現在Moq中,Lambda Expression參數支持是一個未解決的問題,針對的是最終的4.0版本: Moq未解決的問題

修復了使用lambda表達式參數進行模擬的問題,但是僅適用於簡單的lambda表達式。 你可以在這里得到

最后,我改變了主意。 回歸本源。

我需要知道的是是否使用正確的參數調用了Calculator.Add方法。 因此,鑒於它具有單元測試所涵蓋的代理,我認為我應該模擬Calculator對象,並使用真正的代理。 在不更改測試含義的情況下,它比我以前的解決方案更清晰。

使用Moq看起來像這樣:

    [TestMethod]
    public void ParserWorksWithCalcultaroProxy()
    {
        var calculatorMock = new Mock<CalculatorExample.ICalculator>();

         calculatorMock.Setup(x => x.Add(2, 2)).Returns(4).Verifiable();

        var validatorMock = new Mock<ILimitsValidator>();

        var calculatorProxy = new CalculatorProxy(calculatorMock.Object, validatorMock.Object);

        var mathParser = new MathParser(calculatorProxy, new MathLexer(new MathValidator()));
        mathParser.ProcessExpression("2 + 2");

        calculatorMock.Verify();
    }

另外,我也開始更喜歡Moq語法而不是Rhino.Mocks。

暫無
暫無

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

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