2

I am trying to Unittest a method call that waits for a thread to receive a specific value. The thread is polling from an interface several times a second and when there is no information for it, it receives a default message type 0. But when the thread receives a specific message type above 0, it reacts to it. I my case that specific value breaks the wait and the method returns a result. But how do I set this up with Moq?

This question is not about returning a known sequence, but returning an Unknown continuous sequence until a known value is expected.

Here is what i got so far:

        mockedFacade.Setup(facade => facade.RequestPayment()).Callback(
            () =>
            {
                CallbackMessageService.AddMessage(new CallbackMessage{Type = 2, Value = 1});
            }).Verifiable();
        mockedFacade.Setup(facade => facade.GetCallbackMessage()).Returns(CallbackMessageService.GetNextMessage());

I build a test system for creating messages called CallbackMessageService. When the facade calls facade.GetCallbackMessage (2nd setup), it returns a message with type 0 per default. During the test I can then call my CallbackMessageService and add a message to it via CallbackMessageService.AddMessage (1st setup). Next time facade.GetCallbackMessage() is called, the system will return that specific message.

The CallbackMessageService works, but the problem is that the setup for GetCallbackMessage (2nd setup) is somehow caching the first message it receives from the CallbackMessageService. It then always returns the cached message and the CallbackMessageService.GetNextMessage() is never called again. I need to setup it up so CallbackMessageService.GetNextMessage() is always called whenever facade.GetCallbackMessage() is.

How do I accomplish that with Moq?

I assume the caching is a default thing in Moq and I know about the SetupSequence. The problem is I have no control over how many default values i have to handle before the specific value should be returned.

I removed some code to try an isolate the problem. Please let me know if there is to little context.

evilfish
  • 661
  • 8
  • 30
  • Possible duplicate of [Different return values the first and second time with Moq](https://stackoverflow.com/questions/7287540/different-return-values-the-first-and-second-time-with-moq) – krillgar Aug 15 '17 at 12:25
  • @krillgar I understand this looks like a duplicate of these type of question, but these question always knows their exact structure of returns while in my case I do not. I can receive 0 to unlimited default types before i need to return the specific type. – evilfish Aug 15 '17 at 12:38

1 Answers1

0

After I posted the question I continued to tinker with the code and found a solution. This solution only works because the system I test calls another method called facade.CallbackMessageProcessed on the interface before it calls the facade.GetCallbackMessage() again. I could use this to my advantage like so:

mockedFacade.Setup(facade => facade.RequestPayment()).Callback(
    () =>
    {
        CallbackMessageService.AddMessage(new CallbackMessage{Type = 2, Value = 1, MessageID = Guid.NewGuid().ToString()});
    }).Verifiable();
mockedFacade.Setup(facade => facade.GetCallbackMessage()).Returns(CallbackMessageService.GetNextMessage());
mockedFacade.Setup(facade => facade.CallbackMessageProcessed(It.IsAny<CallbackMessage>())).Callback(
    (CallbackMessage c) =>
    {
        CallbackMessageService.MessageResolved(c);
        mockedFacade.Setup(facade => facade.GetCallbackMessage()).Returns(CallbackMessageService.GetNextMessage());
    });

Whenever the CallbackMessageProcessed is called i create a called back where I redo the setup. This continues the loop until the test completes. So it is one way to solve this issue.

I also tried to do the setup in my facade.GetCallbackMessage() callback, but that did not work.

While this is an answer to my specific case it would be nice to see if there is a way to allow for multiple unknown amount of returns on a setup in Moq before another return is expected, if you do not have a second method like I did.

evilfish
  • 661
  • 8
  • 30