{"id":873,"date":"2025-07-13T13:14:36","date_gmt":"2025-07-13T20:14:36","guid":{"rendered":"https:\/\/www.alerainfotech.com\/?p=873"},"modified":"2025-07-13T13:23:19","modified_gmt":"2025-07-13T20:23:19","slug":"the-ultimate-guide-to-mock-injectmocks-and-mockbean-in-spring-boot-testing","status":"publish","type":"post","link":"https:\/\/www.alerainfotech.com\/home\/2025\/07\/13\/the-ultimate-guide-to-mock-injectmocks-and-mockbean-in-spring-boot-testing\/","title":{"rendered":"The Ultimate Guide to\u00a0@Mock,\u00a0@InjectMocks\u00a0and\u00a0@MockBean\u00a0in Spring Boot Testing"},"content":{"rendered":"<h2>\ud83c\udfaf The Ultimate Guide to <code>@Mock<\/code>, <code>@InjectMocks<\/code> and <code>@MockBean<\/code> in Spring Boot Testing<\/h2>\n<p>\u2705 By the end, you\u2019ll know exactly when to use each, how they work under the hood, and what you\u2019re truly testing.<\/p>\n<h3>\ud83d\ude80 Why do we need mocks?<\/h3>\n<p>When writing <strong>unit tests<\/strong>, you want to <strong>test your business logic in isolation<\/strong>, without hitting:<\/p>\n<ul>\n<li>real databases<\/li>\n<li>HTTP calls<\/li>\n<li>or heavy Spring context.<\/li>\n<\/ul>\n<p>Mocks allow us to <strong>fake out dependencies<\/strong>, so we focus purely on what the class itself does.<\/p>\n<h3>\u2699 The three key annotations<\/h3>\n<table>\n<thead>\n<tr>\n<th>Annotation<\/th>\n<th>Where to use it<\/th>\n<th>What it does<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>@Mock<\/code><\/td>\n<td>In pure unit tests<\/td>\n<td>Creates a fake (mock) object of your dependency.<\/td>\n<\/tr>\n<tr>\n<td><code>@InjectMocks<\/code><\/td>\n<td>In pure unit tests<\/td>\n<td>Creates an instance of your class under test and <strong>injects the mocks<\/strong> automatically.<\/td>\n<\/tr>\n<tr>\n<td><code>@MockBean<\/code><\/td>\n<td>In Spring Boot tests (<code>@SpringBootTest<\/code>)<\/td>\n<td>Replaces a Spring Bean in the <strong>application context<\/strong> with a mock.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\ud83d\udd0d The difference, with a story<\/h3>\n<h4>\ud83d\udc47 Example scenario<\/h4>\n<p>Imagine we have:<\/p>\n<ul>\n<li><code>OrderService<\/code> that depends on <code>OrderRepository<\/code>.<\/li>\n<li><code>OrderController<\/code> that depends on <code>OrderService<\/code>.<\/li>\n<\/ul>\n<p><strong>OrderController \u2192 OrderService \u2192 OrderRepository<\/strong><\/p>\n<h3>\ud83e\uddea Unit testing <code>OrderService<\/code><\/h3>\n<p>We want to test <strong>just the logic inside <code>OrderService<\/code><\/strong>, no Spring, no HTTP.<\/p>\n<pre><code class=\"language-java\">\n@ExtendWith(MockitoExtension.class)\nclass OrderServiceTest {\n\n    @Mock\n    private OrderRepository orderRepository; \/\/ creates a fake object\n\n    @InjectMocks\n    private OrderService orderService; \/\/ real service, gets mock injected\n\n    @Test\n    void testGetOrder() {\n        when(orderRepository.findById(1))\n            .thenReturn(Optional.of(new Order(1, \"Laptop\")));\n\n        Order result = orderService.getOrder(1);\n\n        assertEquals(\"Laptop\", result.getName());\n        verify(orderRepository).findById(1);\n    }\n}\n<\/code><\/pre>\n<p>\u2705 <strong>What exactly are we testing?<\/strong><\/p>\n<ul>\n<li>That <code>OrderService<\/code> correctly calls <code>orderRepository.findById()<\/code><\/li>\n<li>Returns the right order<\/li>\n<li>Nothing to do with Spring or HTTP.<\/li>\n<\/ul>\n<h3>\ud83d\ude80 Spring Boot test with <code>@MockBean<\/code><\/h3>\n<p>Now we want to test that <strong>Spring wiring works<\/strong>, i.e.<\/p>\n<ul>\n<li><code>OrderController<\/code> calls <code>OrderService<\/code><\/li>\n<li><code>OrderService<\/code> calls <code>OrderRepository<\/code><\/li>\n<p>but we still don\u2019t want to hit a real DB.<\/p>\n<pre><code class=\"language-java\">\n@SpringBootTest\nclass OrderControllerTest {\n\n    @Autowired\n    private OrderController orderController; \/\/ real bean from Spring\n\n    @MockBean\n    private OrderRepository orderRepository; \/\/ replaces real bean with mock\n\n    @Test\n    void testGetOrder() {\n        when(orderRepository.findById(1))\n            .thenReturn(Optional.of(new Order(1, \"Laptop\")));\n\n        Order result = orderController.getOrder(1);\n\n        assertEquals(\"Laptop\", result.getName());\n        verify(orderRepository).findById(1);\n    }\n}\n<\/code><\/pre>\n<p>\u2705 <strong>What exactly are we testing?<\/strong><\/p>\n<ul>\n<li>That Spring autowires everything properly.<\/li>\n<li>That controller \u2192 service \u2192 repository chain works.<\/li>\n<\/ul>\n<h3>\ud83c\udf10 Testing the HTTP endpoint<\/h3>\n<p>Finally, test the <strong>actual HTTP API<\/strong>, still with mocked repository.<\/p>\n<pre><code class=\"language-java\">\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\n@AutoConfigureMockMvc\nclass OrderControllerHttpTest {\n\n    @Autowired\n    private MockMvc mockMvc;\n\n    @MockBean\n    private OrderRepository orderRepository;\n\n    @Test\n    void testGetOrderHttp() throws Exception {\n        when(orderRepository.findById(1))\n            .thenReturn(Optional.of(new Order(1, \"Laptop\")));\n\n        mockMvc.perform(get(\"\/orders\/1\"))\n               .andExpect(status().isOk())\n               .andExpect(jsonPath(\"$.name\").value(\"Laptop\"));\n    }\n}\n<\/code><\/pre>\n<p>\u2705 <strong>Now we\u2019re testing:<\/strong><\/p>\n<ul>\n<li>The entire Spring Boot stack<\/li>\n<li>JSON serialization<\/li>\n<li>Correct HTTP status codes.<\/li>\n<\/ul>\n<h3>\ud83d\udcdd So when do I use what?<\/h3>\n<table>\n<thead>\n<tr>\n<th>You want to test&#8230;<\/th>\n<th>Use this<\/th>\n<th>Why<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Only class logic, very fast, no Spring<\/td>\n<td><code>@Mock<\/code> + <code>@InjectMocks<\/code><\/td>\n<td>Let Mockito build your class &#038; inject fakes<\/td>\n<\/tr>\n<tr>\n<td>Wiring inside Spring context, no HTTP<\/td>\n<td><code>@SpringBootTest<\/code> + <code>@MockBean<\/code><\/td>\n<td>Spring loads beans &#038; you replace dependencies<\/td>\n<\/tr>\n<tr>\n<td>The full HTTP REST endpoint<\/td>\n<td><code>@SpringBootTest<\/code> + <code>@AutoConfigureMockMvc<\/code> + <code>@MockBean<\/code><\/td>\n<td>Test full HTTP layer with JSON<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\ud83d\udd0d Under the hood: how does <code>@InjectMocks<\/code> work?<\/h3>\n<pre><code class=\"language-java\">\n@InjectMocks\nprivate OrderService orderService;\n\n@Mock\nprivate OrderRepository orderRepository;\n<\/code><\/pre>\n<p>Mockito sees that <code>OrderService<\/code> needs <code>OrderRepository<\/code> and automatically injects it, either via constructor or field. \u2705<\/p>\n<h3>\ud83e\udd47 Key takeaways<\/h3>\n<ul>\n<li>\u2705 Use <code>@Mock<\/code> + <code>@InjectMocks<\/code> for <strong>fast, isolated Java logic tests<\/strong>, no Spring needed.<\/li>\n<li>\u2705 Use <code>@MockBean<\/code> to <strong>replace beans in Spring context<\/strong> when testing controllers or services inside a Spring Boot app.<\/li>\n<li>\u2705 Always clearly decide: <strong>\u201cAm I testing pure logic or Spring wiring or HTTP layer?\u201d<\/strong><\/li>\n<\/ul>\n<h3>\ud83c\udf89 Hope this clears it up once and for all.<\/h3>\n<p>If you liked it, drop a \u2b50 or share it with your team \u2014 so everyone stops being confused by <code>@Mock<\/code>, <code>@InjectMocks<\/code>, and <code>@MockBean<\/code> forever!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83c\udfaf The Ultimate Guide to @Mock, @InjectMocks and @MockBean in Spring Boot Testing \u2705 By the end, you\u2019ll know exactly when to use each, how they work under the hood, and what you\u2019re truly testing. \ud83d\ude80 Why do we need mocks? When writing unit tests, you want to test your business logic in isolation, without [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-873","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/comments?post=873"}],"version-history":[{"count":4,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/873\/revisions"}],"predecessor-version":[{"id":878,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/873\/revisions\/878"}],"wp:attachment":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/media?parent=873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/categories?post=873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/tags?post=873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}