[英]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.