38

I'm currently studying the Mockito framework and I've created several test cases using Mockito. But then I read that instead of invoking mock(SomeClass.class) I can use the @Mock and the @InjectMocks - The only thing I need to do is to annotate my test class with @RunWith(MockitoJUnitRunner.class) or use the MockitoAnnotations.initMocks(this); in the @Before method.

But it doesn't work - It seems that the @Mock won't work! Here is my 2 codes revisions - one using the annotations and one without.

What am I doing wrong?

public class ReportServiceImplTestMockito {

    private TaskService       mockTaskService; // This is the Mock object
    private ReportServiceImpl service;

    @Before
    public void init(){
        service         = new ReportServiceImpl();
        mockTaskService = mock(TaskServiceImpl.class);
        service.setTaskServiceImpl(mockTaskService);
    }
/// ...

 Some tests
}

As I said - this work great. But the following wont:

@RunWith(MockitoJUnitRunner.class)
public class ReportServiceImplTestMockito {

     @Mock 
     private TaskService      mockTaskService;

     @InjectMocks 
     private ReportServiceImpl service;

         // Some tests
}

And here is the ReportServiceImpl class:

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private TaskService taskServiceImpl;

    public ReportServiceImpl(){}

    public ReportServiceImpl(TaskService taskService){
        this.taskServiceImpl = taskService;
    }

    public void setTaskServiceImpl(TaskService taskServiceImpl) {
        this.taskServiceImpl = taskServiceImpl;
    }
}

What am I missing?

rjdkolb
  • 10,377
  • 11
  • 69
  • 89
Noam
  • 3,049
  • 10
  • 34
  • 52
  • Looks OK to me, at first glance. What exactly is going wrong for you? – Dawood ibn Kareem Jan 31 '12 at 08:14
  • 1
    @Noam Are you sure you are using the correct imports ? – bric3 Jan 31 '12 at 08:49
  • David - I'm getting a NullPointerException. And Brice, I believe I'm using the right imports - here they are 'import org.jmock.auto.Mock; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; import org.mockito.runners.MockitoJUnitRunner;' – Noam Feb 01 '12 at 08:45

3 Answers3

32

O.K, I got my mistake!!! I've used the @InjectMocks but initialized the same variable in the init() method... So what happened was that mockito injected the mock objects to my variable - but seconds later I ran it over - initializing that very same variable!!!

Noam
  • 3,049
  • 10
  • 34
  • 52
12

Your code works fine for me using Mockito 1.9.

Using an 1.8+ version of Mockito I get a very specific error message telling me exactly how to fix the problem. As php-coder suggests: For Mockito 1.8+ you need to initialize the field.

Did you see this or any other error message?

Edit:

The following code works for me. Small changes:

  • Removed Spring annotations
  • Removed Interface
  • Added Getter
  • Added empty TaskService
  • Added test with System.out.println

Does it produce an error for you? :

Service:

public class ReportServiceImpl {

    private TaskService taskServiceImpl;


    public ReportServiceImpl() {

    }


    public ReportServiceImpl(TaskService taskService) {
        this.taskServiceImpl = taskService;
    }


    public void setTaskServiceImpl(TaskService taskServiceImpl) {
        this.taskServiceImpl = taskServiceImpl;
    }


    public TaskService getTaskServiceImpl() {
        return taskServiceImpl;
    }
}

Dependency:

public class TaskService {

}

Test, prints mockTaskService:

@RunWith(MockitoJUnitRunner.class)
public class ReportServiceImplTestMockito {

    @Mock
    private TaskService       mockTaskService;

    @InjectMocks
    private ReportServiceImpl service;


    @Test
    public void testMockInjected() {
        System.out.println(service.getTaskServiceImpl());
    }
}
Arend v. Reinersdorff
  • 4,110
  • 2
  • 36
  • 40
  • 1
    As I say, the code works for me. Can you test the code I posted (small changes only)? – Arend v. Reinersdorff Feb 01 '12 at 13:14
  • Hi Arend, sorry for the delay - but your code works for me as well, I've used a worng import for the @Mock annotation - import org.mockito.MockitoAnnotations; instead of import org.mockito.Mock; – Noam Feb 20 '12 at 09:47
3

I'm not sure, but try to create new instance of ReportServiceImpl manually (as you did in working example):

 @InjectMocks 
 private ReportServiceImpl service = new ReportServiceImpl();
Slava Semushin
  • 14,904
  • 7
  • 53
  • 69
  • 3
    This is not anymore necessary since Mockito 1.9 at the exception of edge case. – bric3 Jan 31 '12 at 08:49
  • 2
    If you are using 1.8, you need to instantiate it in the initializer or the constructor unless you are using `MockitoAnnotations.initMocks(this)` in which case, you need to instantiate it before that is called. – jhericks Jan 31 '12 at 16:35
  • 3
    First, thanks for the replies. but useing MockitoAnnotations.initMocks(this) is not neccesary since I used @RunWith(MockitoJUnitRunner.class). – Noam Feb 01 '12 at 08:39