chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hello,

I whould like to know what I do wrong. Fire events inside DoInstead block won't work for me. I reproduce this issue in simple scenario:

public class FooClass
{
    public event EventHandler<EventArgs> FooEvent;

    public void Foo()
    {
        if (FooEvent != null)
        {
            FooEvent(this, EventArgs.Empty);
        }
    }
}

//this test works just fine
[TestMethod]
[Isolated]
public void TestMockes()
{
    bool invoked = false;
    FooClass obj = new FooClass();
    obj.FooEvent += (s, a) => invoked = true;

    Isolate.Invoke.Event(() => obj.FooEvent += null, this, EventArgs.Empty);

    Assert.IsTrue(invoked);
}

//This test is the same as the previous one. I just changed event raising mechanism
[TestMethod]
[Isolated]
public void TestMockesFailure()
{
    bool invoked = false;
    FooClass obj = new FooClass();
    obj.FooEvent += (s, a) => invoked = true;

    Isolate.WhenCalled(() => obj.Foo()).DoInstead((c) =>
        {
            Isolate.Invoke.Event(() => { obj.FooEvent += null; }, this, EventArgs.Empty); //here I have got in runtime the exception below
        });

    obj.Foo();

    Assert.IsTrue(invoked);
}



Exception details:

*** No method calls found in recording block. Please check:
* Are you trying to fake a field instead of a property?
* Are you are trying to fake mscorlib type?

TypeMock.TypeMockException occurred
Message=" *** No method calls found in recording block. Please check: * Are you trying to fake a field instead of a property? * Are you are trying to fake mscorlib type?"
Source="Typemock.ArrangeActAssert"
StackTrace:
at hc.a(Boolean A_0)
at h.a(Action A_0, b6 A_1)
at h.a(Action A_0, Object[] A_1)
at Test.cs:line 115
InnerException:

Can anyone say what can be wrong.
TIA,
Grammer
asked by grammer (1.8k points)

5 Answers

0 votes
Hi Grammer,

There's a limitation in DoInstead that prevents running Isolator faking statements in the custom delegate. In this case, I don't see a good reason right off the bat to block event invocation as well - I'll need to see if we can narrow down the filter to allow these calls.

In the meanwhile, can you try this workaround using method redirection (https://www.typemock.com/Docs/UserGuide/ ... peAAA.html)? This is a pretty powerful mechanism that allows you to redirect calls to custom classes, and work around the limitation in this case by redirecting the call to Foo to a custom implementation:
public class FooClass
{
    public event EventHandler<EventArgs> FooEvent;

    public void Foo()
    {
        if (FooEvent != null)
        {
            FooEvent(this, EventArgs.Empty);
        }
    }
}

public class FooClassSwapper
{
    private readonly FooClass obj;

    public FooClassSwapper(FooClass obj)
    {
        this.obj = obj;
    }

    public void Foo()
    {
        Isolate.Invoke.Event(() => { obj.FooEvent += null; }, this, EventArgs.Empty);
    }
}

[TestMethod]
[Isolated]
public void TestMockesFailure()
{
    bool invoked = false;
    FooClass obj = new FooClass();
    obj.FooEvent += (s, a) => invoked = true;

    var swapper = new FooClassSwapper(obj);
    Isolate.Swap.CallsOn(obj).WithCallsTo(swapper);

    obj.Foo();

    Assert.IsTrue(invoked);
}


Please let me know if this works for you.

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Thank you for your soon response.
Method redirection is great technology. And it is possible to use it in my scenario.

Actually my example is a bit more complex. I have inner objects with inner events I want to raise:

[TestMethod]
[Isolated]
public void TestMockesFailure()
{
    bool invoked = false;
    FooClass obj = new FooClass();
    FooSubClass subObj = new FooSubClass();
    obj.subClass = subObj;

    obj.FooEvent += (s, a) => invoked = true;

    Isolate.WhenCalled(() => subObj.DoSomeInnerTaskAndNotifyMeUponCompletionViaFooInnerEvent()).DoInstead((c) =>
        {
            Isolate.Invoke.Event(() => { subObj.FooInnerEvent += null; }, this, EventArgs.Empty);
        });

    obj.Foo();

    Assert.IsTrue(invoked);
}

//classes
public class FooClass
{
    public event EventHandler<EventArgs> FooEvent;

    public FooSubClass subClass;

    public FooClass()
    {
        subClass = new FooSubClass();
    }

    public void Foo()
    {
        subClass.FooInnerEvent += new EventHandler<EventArgs>(subClass_FooInnerEvent);
        subClass.DoSomeInnerTaskAndNotifyMeUponCompletionViaFooInnerEvent();
    }

    private void subClass_FooInnerEvent(object sender, EventArgs e)
    {
        if (FooEvent != null)
        {
            FooEvent(this, EventArgs.Empty);
        }
    }
}

public class FooSubClass
{
    public event EventHandler<EventArgs> FooInnerEvent;

    public void DoSomeInnerTaskAndNotifyMeUponCompletionViaFooInnerEvent()
    {
        //doo some task
        if (FooInnerEvent != null)
        {
            FooInnerEvent(this, EventArgs.Empty);
        }
    }
}


I have a lot of such subclasses and if I want to use method redirection I have to create swapper class for each subclass like as in example above. That is why using of DoInstead is more preferable in my case.

Have you any other suggestions?

Thank you for your help,
Grammer.
answered by grammer (1.8k points)
0 votes
It seems that the best way for you would be to use Invoke.Event from within DoInstead.

I'll create a patch that allows invoking events from DoInstead you can use.
answered by dhelper (11.9k points)
0 votes
It seems that the best way for you would be to use Invoke.Event from within DoInstead.

I'll create a patch that allows invoking events from DoInstead you can use.


I have used new patch. It works just fine. Thanks.
I wonder whether this patch will be included into official subsequent typemock release?

Thanks,
Grammer
answered by grammer (1.8k points)
0 votes
Hi,

The feature will be part of Isolator from the next version which is about to be released.

The release will contain among the Invoke.Event in DoInstead and other features many improvements to IntelliTest.

Best Regards,
Elisha
Typemock Support
answered by Elisha (12k points)
...