@MockBean返回了空对象。

5

我正在尝试使用@MockBean;Java版本11,Spring框架版本(5.3.8),Spring Boot版本(2.5.1)和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没有被模拟,返回null。


1
你的postEventHandler中该如何使用模拟附件服务?你必须使用Spring机制来创建处理程序,否则它将无法在适当的位置注入模拟对象。 - johanneslink
3个回答

1

我认为你对“模拟(Mock)”的用法有误解。

确实,@MockBean创建了一个模拟对象(内部使用Mockito),并将该对象放置在应用程序上下文中,以便进行注入等操作。

然而,作为程序员,你有责任指定从这个模拟对象调用某个方法时,你期望它返回什么。

因此,假设你的AttachmentService有一个方法String foo(int)

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

您应该使用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);
   }

如果您不指定期望值且您的被测代码某个时刻调用了foo,这个方法调用将会返回null

2
即使添加了上述代码行,在运行testCase时,handlePostBeforeCreate内的attachmentService仍为null。 - bhavya
1
正如@bhavya所说,您的答案并没有真正帮助解决服务为空的问题。 - criztovyl
1
完全没有帮助,似乎他甚至没有读懂问题lol。 - Drumnbass

0

正如 @johanneslink 所说,问题出在这一行:

PostEventHandler postEventHandler = new PostEventHandler();

如果您手动构造PostEventHandler bean,Spring将不会向其注入任何内容。

以下代码应该可以使您的测试工作正常,注意@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", "");
   }
}

0
我遇到了类似的问题:当我同时运行多个测试时(例如,当我运行“mvn clean package”时),模拟的bean中也有null。
如果这是你的情况(或者是其他人看到这篇文章的情况),那么可以通过在每个测试类上注释@DirtiesContext来解决这种情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接