Nzall
Nzall

Reputation: 3565

When stubbing a method in Mockito, should I use the original instance or the stubbed instance for my tests?

I have a Service method I want to test:

public ScheduleView createSchedule(ScheduleView scheduleView) throws ValidationException {
    scheduleView = (ScheduleView) createObject(scheduleView, ScheduleBean.class);
    sendNotificationScheduleDataChangedToSchedulerDaemon();
    return scheduleView;        
}

the sendNotificationScheduleDataChangedToSchedulerDaemon() method makes a connection to a remote service named ServerService, which is not what you want during a unit test. The remote service isn't running during the Unit tests, so the connection fails. I preferably want to stub this method using Mockito so it doesn't get called:

public void testCRUOperations() {
    // Create the service 
    ScheduleService scheduleService = (ScheduleService) ServiceFactory.getInstance().createService(ScheduleService.class);
    ScheduleService scheduleServiceSpy = spy(ScheduleService.class);
    doNothing().when(scheduleServiceSpy).sendNotificationScheduleDataChangedToSchedulerDaemon();

now, my question is, how should I call the createSchedule() method so the stubbed method doesn't get executed?

scheduleView = scheduleService.createSchedule(newscheduleView);

or

scheduleView = scheduleServiceSpy.createSchedule(newscheduleView);

I've tried them both, but the stubbed method still gets executed and I still get ConnectException in my log.

I've checked other questions on here as well as the Mockito framework site, but I can't figure it out. What's the correct way to stub a method?

Upvotes: 0

Views: 57

Answers (1)

Nkosi
Nkosi

Reputation: 247333

This is too long for a comment so putting it here.

I'm not sure about the stubbing but everything else seems to indicate that a refactor should be done. This issue is a clear indicator that the method in question or to what it is interacting with is tightly coupled and should be abstracted out into an inject-able dependency

public interface NotificationService {
    void sendNotificationScheduleDataChangedToSchedulerDaemon();
}

public class ScheduleService {
    private NotificationService notificationService;

    public ScheduleService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }

    public ScheduleView createSchedule(ScheduleView scheduleView) throws ValidationException {
        scheduleView = (ScheduleView) createObject(scheduleView, ScheduleBean.class);
        notificationService.sendNotificationScheduleDataChangedToSchedulerDaemon();
        return scheduleView;        
    }
}

The dependency can now be mocked during unit tests so that it does not hit the actual service and concrete implementation will be used in production code.

Upvotes: 2

Related Questions