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
I'm having trouble testing whether a class subscribes to an event using a private method.

The SystemNodeMenu class below implements a Windows Forms context menu. I want to add an "Edit" item to the menu, and use a private method to handle its Click event.

The first test below fails with the message "No handlers are registered to the event". That happens whether I make the EditItem_Click method private or public. But the second test works if I make the method public.

I've copied the code for both tests from two "Mocking Events" pages in the Developers Guide. Maybe I've made a simple mistake somewhere?


    public class SystemNodeMenu : ContextMenuStrip
    {
        SystemNodePresenter _presenter;
        ToolStripMenuItem   _editItem;

        public SystemNodeMenu( SystemNodePresenter presenter )
        {
            _presenter = presenter;

            _editItem = new ToolStripMenuItem( "&Edit" );
            _editItem.Click += new EventHandler( EditItem_Click );

            Items.AddRange( new ToolStripMenuItem[] { _editItem } );
        }

        //private void EditItem_Click( object sender, EventArgs e )
        public void EditItem_Click( object sender, EventArgs e )
        {
        }
    }


    [ClearMocks]
    [VerifyMocks]
    public class SystemNodeMenuFixture
    {
        [Test]
        public void SubscribeToEditItemClick1()      // This doesn't work
        {
            Mock menuItemMock = MockManager.Mock( typeof( ToolStripMenuItem ) );
            MockedEvent editItemEvent = menuItemMock.ExpectAddEvent( "Click" );

            Mock menuMock = MockManager.Mock( typeof( SystemNodeMenu ) );
            menuMock.ExpectCall( "EditItem_Click" );

            SystemNodePresenter presenterFake = Isolate.Fake.Instance<SystemNodePresenter>();
            menu = new SystemNodeMenu( presenterFake );
            editItemEvent.Fire( this, EventArgs.Empty );
        }

        [Test]
        public void SubscribeToEditItemClick2()      // This works
        {
            SystemNodePresenter presenterFake = Isolate.Fake.Instance<SystemNodePresenter>();
            menu = new SystemNodeMenu( presenterFake );

            MockedEvent editItemEvent;
            using ( RecordExpectations recorder = RecorderManager.StartRecording() )
            {
                ToolStripMenuItem menuItemMock = new ToolStripMenuItem();
                menuItemMock.Click += null;
                editItemEvent = RecorderManager.LastMockedEvent;
                menu.EditItem_Click( null, null );
            }

            // It's ugly creating the menu again, but I'm not sure how to do it otherwise
            menu = new SystemNodeMenu( presenterFake );
            editItemEvent.Fire( this, EventArgs.Empty );
        }
    }
[/code]
asked by denisv (2.8k points)

7 Answers

0 votes
It seems you have a mix of old API (reflective/natural) and new API (AAA) in your test - It could cause some inconsistent behavior.

I've tried to reproduce the issue using the code you've posted but I think that I'm missing some code to make it work properly.

I need more information for further investigation - let's take it offline.
answered by dhelper (11.9k points)
0 votes
Hi Denis,

We tried to email you at the mail you provided when signing up to the forums but failed. Can you follow up with us by emailing support at typemock.com with an updated email address?

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
I think I've worked out what's happening. In the test Instantiate_subscribesToEditItemClick1, the line MockManager.Mock(typeof(SystemNodeMenu)) prevents the SystemNodeMenu constructor further down from being executed, so that the menu object doesn't subscribe to the Click event.

Is there a way I can execute the original constructor and check that the object has subscribed to the Click event via its private method?
answered by denisv (2.8k points)
0 votes
I think I've solved my problem. All I want to know is that the SystemNodeMenu constructor has subscribed to the Click event, and I don't really care what method it uses for the event handler. So all I need is:

Mock menuItemMock = MockManager.Mock( typeof( ToolStripMenuItem ) );
MockedEvent editItemEvent = menuItemMock.ExpectAddEvent( "Click" );

menu = new SystemNodeMenu( presenterFake );

This seems to work OK.
answered by denisv (2.8k points)
0 votes
Hi Doron,

I've just changed the design of the SystemNodeMenu class, and it's led to another problem.

Previously, SystemNodeMenu had a reference to a SystemNodePresenter instance, and when the Edit menu item was clicked it would call the presenter's Edit() method. I could easily test that by faking a presenter instance and checking that its Edit() method had been called.

But that design doesn't conform to the MVP pattern, where the view has no reference to the presenter. So I've modified the SystemNodeMenu class to raise an Edit event when its Edit menu item is clicked, and then the presenter responds to that event as follows:

    public class SystemNodeMenu : ContextMenuStrip
    {
        public event EventHandler Edit;

        public SystemNodeMenu( SystemNodePresenter presenter )
        {
            ToolStripMenuItem _editItem = new ToolStripMenuItem( "&Edit" );
            _editItem.Click += EditItem_Click;

            Items.AddRange( new ToolStripMenuItem[] { _editItem } );
        }

        private void EditItem_Click( object sender, EventArgs e )
        {
            if ( Edit != null )
                Edit( sender, e );
        }
    }


    public class SystemNodePresenter
    {
        public void ContextMenu( TreeNode treeNode )
        {
            SystemNodeMenu menu = new SystemNodeMenu();
            menu.Edit += Edit;
            menu.Show();
        }

        public void Edit( object sender, EventArgs e )
        {
            // Do something
        }
    }

It's easy to test if the SystemNodePresenter subscribes to the Edit event, but is there a simple way to test if SystemNodeMenu actually fires the Edit event when its menu item is clicked?

Denis
answered by denisv (2.8k points)
0 votes
Hi Denis,

You can simply place an expectation on the event handler method and verify that expectation - this way, if the event was called you verify the handler was called. You can also create a dummy event handler and register it, and verify against that.

Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Thanks for that, Doron.

I tried both ways that you suggested. First I verified that the private event handler was called (using the Constructor.NotMocked option when I created the mock). But that didn't verify that the event was actually being raised - which wasn't happening anyway because I forgot to add the code!

So because it takes quite a lot of work to set up a fake presenter that subscribes to the Edit event, I created the following test class to do so:

    public class AreaNodeMenuTest
    {
        AreaNodeMenu _menu;

        public AreaNodeMenuTest( AreaNodeMenu menu )
        {
            _menu = menu;
            menu.Edit += Edit;
        }

        void Edit( object sender, EventArgs e )
        {
        }
    }


I mocked that class and verified that its Edit method was called menu's Edit item was clicked.

Thanks again for your help.

Denis
answered by denisv (2.8k points)
...