3

Keeping in mind the answers on this question Settings variable values in a Moq Callback() call, which is how I came to understand (or so I thought) I can defer the execution of the Returns, I'm not able to get it to work.

this.mock = new Mock<ICriteria>();
this.mock
    .As<IRuleProcessor<Input, Output>>()
    .Setup(m => m.Process(It.IsAny<Input>()))
    .Returns((Input input) => new Output
    {
        ExecutionStatus = executionStatus
    });

where the aforementioned code is executed in [TestInitialize] and executionStatus is defined like this:

private RuleExecutionStatus executionStatus = RuleExecutionStatus.Success;

and finally, executionStatus is modified like this:

executionStatus = RuleExecutionStatus.FailedValidation;

in the test I'm executing before the SUT is executed. Now, when an internal method to the SUT is executed it calls Process on the mock setup above. However, it's not grabbing the modified value, it's only grabbing the initial value.

Keep in mind, it wouldn't surprise me if I've set this up wrong.

How can I achieve modifying this status for one test in the class? All other tests need the success status.

Does it have something to do with the .As<IRuleProcessor<Input, Output>>()? Does deferred execution like this not work when I have to setup a method on an inherited interface?

Community
  • 1
  • 1
Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • Have you tried putting a breakpoint in the `Func` you pass to `Returns` to see when it actually gets executed? – Steve Ruble May 02 '14 at 14:56
  • @SteveRuble, yes I have. That is one of the two reasons I know it's not deferring. The first reason being that it's not working of course. – Mike Perrenoud May 02 '14 at 14:58
  • it seems really strange that the delegate would be executed immediately. What is the value of `input` when it gets executed? – Steve Ruble May 02 '14 at 15:02
  • Can you post your test code? I tried it here, and it seems to work fine; The return lambda is called each time. – Bruno Brant May 02 '14 at 15:03
  • 1
    When the break-point is hit, observe the Call Stack, to find out who called the delegate inside the `Returns`. – Mohammad Dehghan May 02 '14 at 15:04
  • @MD.Unicorn, the break point is never hit. – Mike Perrenoud May 02 '14 at 15:06
  • 2
    Well, that obviously means that the code `ExecutionStatus = executionStatus` is never run, so the value is being changed from somewhere else. Am I missing something? Put a break-point inside the `set` part of the `ExecutionStatus` property to find out who is setting it. – Mohammad Dehghan May 02 '14 at 15:09
  • If the breakpoint is never hit, how can you know it's actually calling the method and takes its value? Maybe there is a bug in the implementation you test? – treze May 02 '14 at 15:09
  • @BrunoBrant: so with you saying that I had to start wondering. I found somebody else setting it up after my call somewhere down the line. My apologies. – Mike Perrenoud May 02 '14 at 15:11
  • @MD.Unicorn: yeah can't do that, it's not my class, it comes from a dependency. However, I did find the culprit. I wish I had originally written these test classes, it would never be this messy! – Mike Perrenoud May 02 '14 at 15:12
  • @MichaelPerrenoud, no apologies needed. We've all been there. – Bruno Brant May 02 '14 at 21:01
  • I meet the same problem. it seems the code in Returns() will be execute when the mock object is created instead of when execute the target mock method. does someone know how to defer the code in Returns() to execute when invoking the mocked method? – RyanShao Jan 05 '16 at 03:09
  • 1
    @RyanShao if I remember correctly the key there is to send in a lambda expression. – Mike Perrenoud Jan 05 '16 at 03:47
  • @MichaelPerrenoud I resolved the problem by Throws method, it is guaranteed to be only executed when the mock method is actually invoked. – RyanShao Jan 12 '16 at 03:43

0 Answers0