I'm trying to use multiple Mock.Setup() invocation for the same mocked object method.
It works fine, when i'm using code like that:
[TestMethod]
pubblic void TestMethod1()
{
var mock = new Mock<ITestInt>();
mock.Setup(_ => _.Do(true)).Returns(1);
mock.Setup(_ => _.Do(false)).Returns(-1);
//---
var trueResult = mock.Object.Do(true);
var falseResult = mock.Object.Do(false);
//---
Assert.AreEqual(trueResult,1); // true
Assert.AreEqual(falseResult, -1); // true
}
But, when i'm trying to execute Mock.Setup() method with Expression
[TestMethod]
public void TestMethod2()
{
var mock = new Mock<ITestInt>();
Expression<Func<bool>> func = () => It.Is<bool>(_ => true);
mock.Setup(_ => _.Do(func.Compile().Invoke())).Returns(1);
Expression<Func<bool>> func2 = () => It.Is<bool>(_ => false);
mock.Setup(_ => _.Do(func2.Compile().Invoke())).Returns(-1);
//---
var trueResult = mock.Object.Do(true);
var falseResult = mock.Object.Do(false);
//---
Assert.AreEqual(trueResult, 1); // true
Assert.AreEqual(falseResult, -1); // FAIL, falseResult equals 1 instead of -1
}
@msharonov:
But, when i'm trying to execute Mock.Setup() method with Expression
, it fails. A little code example: [...]
Your second code example does not make any sense to me. Could you perhaps show the definition of the ITestInt.Do method that goes along with it, as well as a description what you're trying to achieve with the second test? Why is it so radically different from the first test?
Of course, my bad. Here is the whole ITestInt simple interface definition:
public interface ITestInt
{
int Do(bool arg);
}
I'm trying to archieve only one goal: take ability to define mocking method args with an expression, that received outside of initalization method. Little exampple
[TestMethod]
public void TestMethod3()
{
var mock = new MockDefinition();
mock
.Setup(() => It.Is<bool>(_ => true), 1)
.Setup(() => It.Is<bool>(_ => false), -1);
//---
var trueResult = mock.Do(true);
var falseResult = mock.Do(false);
//---
Assert.AreEqual(trueResult, 1);
Assert.AreEqual(falseResult, -1); // fails here
}
public sealed class MockDefinition : ITestInt
{
private readonly Mock<ITestInt> _mock = new Mock<ITestInt>();
public MockDefinition Setup(Expression<Func<bool>> setupFuncExp, int result)
{
_mock.Setup(_ => _.Do(setupFuncExp.Compile().Invoke())).Returns(result);
return this;
}
public int Do(bool arg)
{
return _mock.Object.Do(arg);
}
}
Why all the Expression stuff? Why don't you just use a plain bool argument instead of an Expression<Func<bool>>?
Because in real life It.Is<bool>(_ => true) can be replaced with It.Is<bool>(_ => _.Id > 0 && _.Id < 1000) or something else, that can't be specified with a simple plain arg value.
Well in that case the problem can be reduced to passing the proper expression tree to Setup.
Note that Setup expects an expression tree. Therefore .Compile().Invoke() won't be executed, but instead it'll be transformed to an equivalent LambdaExpression. That's not what you want.
You will likely need to build the whole expression yourself, e.g. Expression.Call(setupMockParamExpr, typeof(ITestInt).GetMethod("Do"), exprRepresentingCallToMatcherFn) and pass that as the expression body to Setup.
This appears to be a pure usage question (not a request for an enhancement, nor a bug report) and it's mostly about LINQ expression trees, as far as I can tell. Do you agree?
Oh. Yes, you're right. Thanx!)
Most helpful comment
Because in real life
It.Is<bool>(_ => true)can be replaced withIt.Is<bool>(_ => _.Id > 0 && _.Id < 1000)or something else, that can't be specified with a simple plain arg value.