I am writing the test cases for my controller class which is a Spring Boot Application and I want to write the test cases only for controller class which invokes Service and Service to Repository. I am using SpringBootTest which is used for to create the instances for all of my beans. I want to mock only Database calls and external api calls.
MyController {
@Autowired
MyService service;
//Api call for getDetails
service.getDetails();
}
MyService {
@Autowired
MyRepository repo;
}
MyControllertest {
@Autowired
MyController controller;
@Mock
MyRepository repoMock;
@Before
public void setup(){
// intit mocks
}
@Test
public void myTest(){
when(repoMock.getDetails()).thenReturn(null);
controller.getdetails();
}
}
When I run the test case, it is not using the mock Repository, instead of that using the @Autowired
Repository which is mentioned in the Service class.
Can anyone please explain me how to mock the repository from controller class.
Posting so many questions in this blog, but am not getting any responses.
Spring Boot Rest Controller JUnit test cases example with Mockito. Unit tests are used to test the smaller units of an application. Unit tests make sure that a unit of code is working as expected. There are many unit testing frameworks available in Java. Example: TestNG, JUnit, Mockito, etc.
@MockBean: This annotation creates mocked beans in the spring application context. @Test: Indicated that the method is a test case. Mockito: This class of Mockito framework creates a mock of an object. We have mocked the return values of the service layer in our example.
@MockMVCTest : annotation is used for Spring MVC tests. It disables full auto-configuration and instead apply only configuration relevant to MVC tests. @MockMvc : is a class part of Spring MVC Test which help you to test controllers explicitly starting a Servlet container.
But the best kind of test doesn’t use Spring at all, so let’s first look at how to use Mockito in a plain unit test to mock away unwanted dependencies. The plainest way to use Mockito is to simply instantiate a mock object using Mockito.mock () and then pass the so created mock object into the class under test:
It is not using your Mocks because you are not injecting those mocks into your controller / service classes. Instead you are Autowiring it.
Correct way to do it is
@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
@InjectMocks
MyController controller;
.....
}
Even better solution would be to get rid of Field Injection and use Constructor Injection
For example in your Controller and Service class. Instead of using @Autowired on Fields you can do it on Contructor. For example
class MyService {
private final MyRepository repo;
@Autowired
public MyService(final MyRepository repo) {
this.repo = repo;
}
}
Similarly in Controller class
class MyController {
@Autowired
private final MyService service;
public MyController(final MyService service) {
this.service = service
}
}
Doing this way will help you in setting mocks easily during runtime. For example in your test class you could do
@RunWith(MockitoJUnitRunner.class)
public class MyControllertest {
MyController controller;
MyService service;
@Mock
MyRepository repoMock;
@Before
public void setup(){
// init mocks
service = new MyService(repoMock);
controller = new MyController(service);
}
..............
}
Here is a nice article about Field injection
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With