Search code examples
visual-studio-2010unit-testingmockingmolespex-and-moles

How to call delegate only once / one time with moles?


How is it possible to call a delegated Method only once / one time with moles?

MyClass.AllInstances.ResultateGet = delegate { return new ResultatInfoCollection(); };

I want to call the Method "ResultateGet" only one time because the init is quite complex the first time without a delegate.

target.UpdateResultate(); //calls delegate "ResultateGet"
//Assert some stuff
target.Verify(); //needs original function "ResultateGet" so unit test is useful

I am generally interested how to call a moles delegate one time ore a specific number of times before the original function is called and not the delegate.

Update: I found a way, that seems a little bit cumbersome. Any better Solution?

ResultatInfoCollection x = new ResultatInfoCollection();
MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);

Solution

  • Also, see my answer to: How to assign/opt from multiple delegates for a 'moled' method? This provides an example of gating logic inside the anonymous method.

    Ooh, good question! I have encountered this, myself. What you are looking for is called a "fallthrough" behavior (execution of the original code). The anonymous method to which Moles detours must contain a switching mechanism that falls through, after the first call. Unfortunately, I don't believe a fallthrough feature is included in Moles, at this time.

    Your updated workaround is exactly what you need -- calling fallthrough would do the same thing. I suggest adding a sentinel value, doFallthrough, that gates the calls:

    bool doFallthrough = false;
    ResultatInfoCollection x = new ResultatInfoCollection();
    MyClass.AllInstances.ResultateGet = delegate { 
        if (!doFallthrough)
        {
            doFallthrough = true;
            return new ResultatInfoCollection();
        }
        MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
    };
    

    Calling a specific number of times simply requires a change to the sentinel value type:

    int doFallthrough = 0;
    ResultatInfoCollection x = new ResultatInfoCollection();
    MyClass.AllInstances.ResultateGet = delegate { 
        if (++doFallthrough < 5)
            return new ResultatInfoCollection();
        MolesContext.ExecuteWithoutMoles(() => x = target.Resultate);
    };