@MockBean is returning null object

Viewed 2724

I am trying to use @MockBean; java version 11, Spring Framework Version (5.3.8), Spring Boot Version(2.5.1) and Junit Jupiter (5.7.2) .

    @SpringBootTest
    public class PostEventHandlerTest {
        @MockBean
        private AttachmentService attachmentService;

        @Test
        public void handlePostBeforeCreateTest() throws Exception {
            Post post = new Post("First Post", "Post Added", null, null, "", "");
            
            Mockito.when(attachmentService.storeFile("abc.txt", "")).thenReturn(new Attachment());
     
            PostEventHandler postEventHandler = new PostEventHandler();
            postEventHandler.handlePostBeforeCreate(post);
            verify(attachmentService, times(1)).storeFile("abc.txt", "");
       }
    }
    @Slf4j
    @Component
    @Configuration
    @RepositoryEventHandler
    public class PostEventHandler {
           @Autowired
           private AttachmentService attachmentService;

           @Autowired
           private PostRepository postRepository;

           public void handlePostBeforeCreate(Post post) throws Exception {
             ...
             /* Here attachmentService is found null when we execute above test*/
             attachmentService.storeFile(fileName, content);
             ...
           }
    }

attachmentService is not being mocked it gives null in return

3 Answers

I think you misunderstand the usage of Mocks.

Its true that @MockBean creates a mock (internally uses Mockito) and puts this bean onto an application context so that it will be available for injections, etc.

However, its for your responsibility as a programmer to specify what do you expect from this mock to return when you call one method or another on it.

So, assuming your AttachementService has a method String foo(int):

public interface AttachementService { // or class 
   public String foo(int i);
}

You should specify the expectations with the help of Mockito API:

    @Test
    public void handlePostBeforeCreateTest() throws Exception { 
        // note this line, its crucial
        Mockito.when(attachmentService.foo(123)).thenReturn("Hello");

        Post post = new Post("First Post", "Post Added", null, null, "", "");
        PostEventHandler postEventHandler = new PostEventHandler();
        postEventHandler.handlePostBeforeCreate(post);
        verify(attachmentService, times(1)).storeFile("", null);
   }

If you won't specify the expectation and if your code-under-test calls foo at some point, this method call will return null

I met a similar problem: I also had null in mocked bean, but only when I run several tests at once (for example, when I run "mvn clean package")

If it was your case (or if it case of someone, who will see this post), then this situation might be solved by annotation @DirtiesContext on every test class youre running

As @johanneslink said, the problem is this line:

PostEventHandler postEventHandler = new PostEventHandler();

Spring won't inject anything into your PostEventHandler bean if you manually construct it.

The following should make your test work, note the @Autowired postEventHandler. :)

@SpringBootTest
public class PostEventHandlerTest {

    @MockBean
    private AttachmentService attachmentService;

    @Autowired
    PostEventHandler postEventHandler;
    
    @Test
    public void handlePostBeforeCreateTest() throws Exception {
    
        Post post = new Post("First Post", "Post Added", null, null, "", "");
        
        Mockito.when(attachmentService.storeFile("abc.txt", "")).thenReturn(new Attachment());

        postEventHandler.handlePostBeforeCreate(post);
        
        verify(attachmentService, times(1)).storeFile("abc.txt", "");
   }
}
Related