2

I'm having trouble determining how to mock a particular piece of code.

Here is my method:

public void sendNotifications(NotificationType type, Person person)
    {
        List<Notification> notifications = findNotifications(type);
        for(Notification notification : notifications)
        {
            notification.send(person);
        }
    }

I would like to be able to use JMock to test that findNotifications is called and that and returns the expected value and that send() is called.

findNotifications calls my Dao which is mocked. Notification is an abstract class.

I have a unit test like this, but it's obviously not working. It satisfies the first two expectations but no more.

    @Test
public void testSendNotifications2()
{
    final Person person = new Person();
    notificationEntries.add(createEntry1);

    Mockery context = new JUnit4Mockery() {{ setImposteriser(ClassImposteriser.INSTANCE); }};
    final NotificationDao dao = context.mock(NotificationDao.class, "notificationDao");
    final Notification mockedNotification = context.mock(V2ADTNotification.class, "mockNotification");
    notifications.add(mockedNotification);

    final NotifierServiceImpl mockedService = context.mock(NotifierServiceImpl.class, "mockedService");

    //NotifierService service = new NotifierServiceImpl(dao);

    context.checking(new Expectations() {
        {
            one(mockedService).setDao(dao);
            one(mockedService).sendNotifications(NotificationType.CREATE, person);
            one(mockedService).findNotifications(NotificationType.CREATE);
            one(dao).getByNotificationType(NotificationType.CREATE);
            will(returnValue(notificationEntries)); 
            will(returnValue(notifications));

            one(mockedNotification).send(person);
        }
    });

    mockedService.setDao(dao);
    mockedService.sendNotifications(NotificationType.CREATE, person);
    context.assertIsSatisfied();
}

    mockedService.sendNotifications(NotificationType.CREATE, person);
    context.assertIsSatisfied();
}

How could I get this to work as I want it to?

Another way I tried. It satisfies the first two expectations but not the send one.

@Test
public void testSendNotifications()
{
    final Person person = new Person();
    notificationEntries.add(createEntry1);

    Mockery context = new JUnit4Mockery() {{ setImposteriser(ClassImposteriser.INSTANCE); }};
    final NotificationDao dao = context.mock(NotificationDao.class, "notificationDao");
    final Notification mockedNotification = context.mock(V2ADTNotification.class, "mockNotification");

    NotifierService service = new NotifierServiceImpl(dao);

    context.checking(new Expectations() {
        {
            one(dao).getByNotificationType(NotificationType.CREATE);
            will(returnValue(notificationEntries)); 

            one(mockedNotification).send(person);
        }
    });

    service.sendNotifications(NotificationType.CREATE, person);
    context.assertIsSatisfied();
}

I'm pretty new to using Jmock so I apologize if it doesn't look like I have much of a clue as to what I'm doing (I don't).

AHungerArtist
  • 9,332
  • 17
  • 73
  • 109

1 Answers1

4

test mocked methods inside a mocked method.

You really just can't do that. The calls in the real method aren't being made, because you're calling the mock instead of the real method.

Your first attempt fails the last two expectations because the calls that would make them pass are made only in the real implementation of sendNotifications, and not in the mock that you made of it.

The second is closer to workable, but you need to add your mockedNotification to the notificationEntries list that you've set up to be return by the mock of getByNotificationType.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
  • I figured as much but didn't know for sure if I was missing something. I took a different route. Inside the findNotifications method I was using a static factory. I've decided to make the factory an injectable class instead of a static one, so now I'm mocking it and now I can test for the behavior I want (otherwise I never would have been able to get the mocked Notification objects instead of just the mocked NotificationEntry objects -- probably should have included more code). I'll mark your answer as correct since it does address my problem and I've explained my solution in this comment. – AHungerArtist Apr 13 '11 at 21:56