2

I have an interface ILogger that has a LocalTime property to which one could add time with AddToTime. To mock it appropriately, I tried the following:

int ltime = 0;
var mlog = new Mock<ILogger>();
mlog.Setup(l => l.AddToTime(It.IsAny<int>())).Callback((int s) => {ltime +=s;});
mlog.Setup(l => l.LocalTime).Returns(ltime);

Although it compiles, i does not work: Probably because Returns evaluates the expression ltime at the beginning and so always returns 0. Any suggestions how one could achieve the indented behaviour?

Edit: I need this to test it with a loop looking like this:

while (log.LocalTime < 1000)
        {
            log.AddToTime(500);
             ....
         }

As I use the time for logging purposes, it cannot simply replaced by a loop with a local variable. If AddToTime does nothing, the loop cannot be properly tested.

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142

2 Answers2

4

This is a test, I suggest you to avoid any logic in your test. Only place where you should have some logic is SUT you are testing. Otherwise implementation of mocked logger sneaks into test of some other class. Simply setup values you are expecting:

int ltime = 0;
int timeToAdd = 2;
var mlog = new Mock<ILogger>();
mlog.Setup(l => l.AddToTime(timeToAdd));
mlog.Setup(l => l.LocalTime).Returns(ltime + timeToAdd);

I'd even try to avoid last return setup calculation and replaced it with constant expected value. But I need to know more about logic you are testing.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • The interface is used in a loop which exits after a time limit is reached. So setting constant values leads to an infinite loop or not invocation at all. Alternatively, I need something that returns a low LocalTime at first invocation, and a high value for any further invocation. – J Fabian Meier Dec 13 '13 at 09:19
0

You can use the Returns method instead of the Callback
Example here: Settings variable values in a Moq Callback() call

Community
  • 1
  • 1