0

I realized while writing unit testing in two different projects that the behavior of setup in Moq is different than Stub in Rhino-Mocks.

One class uses Mock which has one of these scenarios where I stub

for (int i=0; i<ObjectAList.Count; i++)
{
     _translator.Stub(x => x.TranslateToObjectB(ObjectAList[i])).Return(ObjectBList[i]);
}

the above example works like a charm.

But when I tried to do the same thing in a different project that uses Moq, using setup, it failed.

for (int i=0; i<ObjectAList.Count; i++)
{
     _translator.SetUp(x => x.TranslateToObjectB(ObjectAList[i])).Returns(ObjectBList[i]);
}

Instead I had to do something like this,

int i = 0;
foreach (var ObjectA in ObjectAList)
{
     _translator.Setup(x => x.ConvertToProcessingFilter(ObjectA)).Returns(ObjectBList[i]);
     i++;
}

I am just looking for a reason why stub vs setup behaved so differently. If this is the expected from setup, then what is the equivalent of stub in Moq ?

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
Ani
  • 4,473
  • 4
  • 26
  • 31

1 Answers1

0

What you see, is related to Closures behaving differently in for and foreach loops.

With:

for (int i=0; i<ObjectAList.Count; i++)
{
     _translator.Setup(x => x.TranslateToObjectB(ObjectAList[i])).Returns(ObjectBList[i]);
}

you are closing over (capturing) the for iteration variable. The behavior will depend on when the mocking framework evaluates the lambda expression.

Try:

for (int i=0; i<ObjectAList.Count; i++)
{
     var j = i;
     _translator.Setup(x => x.TranslateToObjectB(ObjectAList[j])).Returns(ObjectBList[j]);
}

instead. Will it work?

You might also be able to do just one setup, similar to this:

_translator.Setup(x => x.TranslateToObjectB(It.IsAny<ObjAType>()))
  .Returns((ObjAType a) => ObjectBList[ObjectAList.IndexOf(a)]);
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181