Trying to get JUnit with mockito testing to work and getting a NPE on my test here. I'm wanting to have a verify that when createRegistrant(registrationDTO) is called, saveUpdateRegistration(Registration reg) method is called right after. An issue I find strange is that on Mockito.verify(registrationServiceImpl, Mockito.times(1)).createRegistrant(registrationDTO); it is not suggesting I can test if saveUpdateRegistration(Registration reg) method was called? IntelliJ only suggests methods that are in my interface?
My test code below:
#RunWith(MockitoJUnitRunner.class)
public class RegistrationServiceImplTest {
#InjectMocks
private RegistrationServiceImpl registrationServiceImpl;
#Mock
private RegistrationDTO registrationDTO;
#Mock
private Registration registration;
#Before
public void setup() {
registrationDTO.seteId("abc123");
registrationDTO.setTech("AWS");
registrationDTO.setFirstName("Bob");
registrationDTO.setLastName("Tom");
}
#Test
public void createRegistrant() throws Exception {
// Mockito.when(registrationServiceImpl.createRegistrant(registrationDTO)).thenReturn(registrationDTO);
Mockito.when(registrationServiceImpl.createRegistrant(registrationDTO)).thenReturn(registrationDTO);
registrationServiceImpl.createRegistrant(registrationDTO);
Mockito.verify(registrationServiceImpl, Mockito.times(1)).createRegistrant(registrationDTO);
}
Here is the code I'm testing:
package com.TechODex.service;
import com.TechODex.dto.RegistrationDTO;
import com.TechODex.model.Registration;
import com.TechODex.dao.RegistrationDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
#Service
#Transactional
public class RegistrationServiceImpl implements RegistrationService {
#Autowired
private RegistrationDAO registrationDAO;
public RegistrationDTO createRegistrant(RegistrationDTO reg) {
saveUpdateRegistration(setDTOToModel(reg));
return reg;
}
public void deleteRegistrant(Long id) { deleteUserRegistrant(id); }
public List<Registration> findAllRegistrant(String tech) { return findAllRegistrantDAO(tech);}
public List<Registration> findAllTech() { return findAllTechDAO();}
private Registration setDTOToModel(RegistrationDTO dto){
Registration registration = new Registration();
registration.setFirstName(dto.getFirstName());
registration.setLastName(dto.getLastName());
registration.seteId(dto.geteId());
registration.setTech(dto.getTech());
return registration;
}
private void saveUpdateRegistration(Registration reg){ registrationDAO.save(reg);}
}
There are several issues here.
First, you do not mock RegistrationDAO. This will lead to it being null in the class under test. Next, RegistrationService is not a mock, yet you try to use when and verifyon it. Last, RegistrationDTO is mocked, so the invocations to the setters in #Before has no effect.
Your test should look something like:
#RunWith(MockitoJUnitRunner.class)
public class RegistrationServiceImplTest {
#InjectMocks
private RegistrationServiceImpl registrationServiceImpl;
#Mock
private RegistrationDAO registrationDAO;
private RegistrationDTO registrationDTO;
private Registration registration;
#Before
public void setup() {
registration = new Registration();
registration.seteId("abc123");
registration.setTech("AWS");
registration.setFirstName("Bob");
registration.setLastName("Tom");
registrationDTO = new RegistrationDTO();
registrationDTO.seteId("abc123");
registrationDTO.setTech("AWS");
registrationDTO.setFirstName("Bob");
registrationDTO.setLastName("Tom");
}
#Test
public void createRegistrant() throws Exception {
final RegistrationDTO result = registrationServiceImpl.createRegistrant(registrationDTO);
assertSame(registrationDTO, result);
verify(registrationDAO).save(eq(registration));
}
}
given that Registration has an implemented equals-method where the fields that are set are compared. If not, you need to use an ArgumentCaptor.
Related
Im trying to test a controller, Author Controller, which returns a view with a model. The problem is on the testInitUpdateAuthor() test where its not able to find the model or attribute name specifically. All other methods are fine with their model/attribute tests.
Any advice?
#Slf4j
#Controller
public class AuthorController {
private final AuthorService authorService;
private final String CREATEORUPDATEFORM = "author/createOrUpdateAuthor";
public AuthorController(AuthorService authorService) {
this.authorService = authorService;
}
#GetMapping("/author/{id}/update")
public String updateAuthor(#PathVariable("id") Long id, Model model) {
model.addAttribute("author", authorService.findById(id));
return CREATEORUPDATEFORM;
}
#ExtendWith(MockitoExtension.class)
#SpringBootTest
class AuthorControllerTest {
MockMvc mockMvc;
#Mock
AuthorService authorService;
#InjectMocks
AuthorController authorController;
#BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(authorController).build();
}
#Test
void getIndex() throws Exception {
mockMvc.perform(get("/author/index"))
.andExpect(status().isOk())
.andExpect(view().name("author/index"))
.andExpect(model().attributeExists("authors"));
}
#Test
void testInitUpdateAuthor() throws Exception {
when(authorService.findById(anyLong())).thenReturn(Author.builder().id(1L).build());
mockMvc.perform(get("/author/1/update"))
.andExpect(status().isOk())
.andExpect(view().name("author/createOrUpdateAuthor"))
.andExpect(model().attributeExists("author"));
}
}
I am having dificulties with using MockMvc.
Here I have simple Service and controller classes:
Service:
#Slf4j
#Service
public class EmployeeService {
//...
public Employee GetSample() {
//...
//filling Employee Entities
return new Employee(
"Harriet"
, "random"
, 25);
}
}
controller:
#RestController
#RequestMapping(value = "/info")
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#Validated
public class EmployeeController {
private final EmployeeService employeeService;
#PostMapping("/GetEmployee")
public ResponseEntity<Employee> GetEmployee() {
Employee employee = employeeService.GetSample();
return new ResponseEntity<>(employee, HttpStatus.OK);
}
}
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EmployeeTestCase {
private MockMvc mockMvc;
#InjectMocks
private EmployeeController EmployeeController;
#Mock
private EmployeeService employeeService;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.standaloneSetup(employeeController).build();
}
#Test
public void getEmployee() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/info/GetEmployee")).andDo(print());
}
}
when I try to use MockMvc I get null body. It seems employee is null. But I didn't understand why.
I thought that when test uses perform, it should initialise employee and later on it should't be null.
I tried to cut the code as much as possible. I hope it is not long.
Note : also tried to use Mockito.when(employeeController.GetEmployee()).thenCallRealMethod();
The #SpringBootTest annotation loads the complete Spring application
context. That means you do not mock your layers
(Services/Controllers).
If you wanted to test specific layers of your application, you could look into test slice annotations offered by Springboot: https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html
In contrast, a test slice annotation only loads beans required to test a particular layer. And because of this, we can avoid unnecessary mocking and side effects.
An example of a Test Slice is #WebMvcTest
#ExtendWith(SpringExtension.class)
#WebMvcTest(controllers = HelloController.class,
excludeFilters = {
#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
}
)
public class HelloControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void hello() throws Exception {
String hello = "hello";
mvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string(hello));
}
#Test
public void helloDto() throws Exception {
String name = "hello";
int amount = 1000;
mvc.perform(
get("/hello/dto")
.param("name", name)
.param("amount", String.valueOf(amount)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is(name)))
.andExpect(jsonPath("$.amount", is(amount)));
}
}
However if you really wanted to load up the SpringBoot Application context, say for an Integration Test, then you have a few options:
#SpringBootTest
#AutoConfigureMockMvc
public class TestingWebApplicationTest {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello, World")));
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class AuctionControllerIntTest {
#Autowired
AuctionController controller;
#Autowired
ObjectMapper mapper;
MockMvc mockMvc;
#Before
public void setUp() throws Exception {
System.out.println("setup()...");
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test
public void create_ValidAuction_ShouldAddNewAuction() throws Exception {
final Auction auction = new Auction(
"Standing Desk",
"Stand up desk to help you stretch your legs during the day.",
"Johnnie34",
350.00);
mockMvc.perform(post("/auctions")
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(auction)))
.andExpect(status().isCreated());
}
}
Lets say you don't want to load up any layers at all, and you want to mock everything, such as for example a Unit Test:
#RunWith(MockitoJUnitRunner.class)
class DemoApplicationTest {
#Mock
private UserRepository userRepository;
private Demo noneAutoWiredDemoInstance;
#Test
public void testConstructorCreation() {
MockitoAnnotations.initMocks(this);
Mockito.when(userRepository.count()).thenReturn(0L);
noneAutoWiredDemoInstance = new Demo(userRepository);
Assertions.assertEquals("Count: 0", noneAutoWiredDemoInstance.toString());
}
}
I set up following pact contract provider test
#RunWith(SpringRestPactRunner.class)
#Provider("structures")
#PactFolder("pacts")
#VerificationReports({"console", "markdown"})
#SpringBootTest
public class ContractTest {
#MockBean
private MyServiceImpl myServiceImpl;
#Autowired
private MyController myController;
#Configuration
public static class TestConfiguration {
#Bean
public MyController myController() {
return new MyController();
}
}
#TestTarget
public final MockMvcTarget target = new MockMvcTarget();
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
target.setControllers(myController);
}
#State("My state")
public void setupDocumentWithStructures() {
Mockito.when(myService.getStructuresByDocumentId(
ArgumentMatchers.eq("1"),
ArgumentMatchers.any()
)).thenReturn(new PageImpl<>(Arrays.asList(
Structure.of("first"),
Structure.of("second")
)));
}
}
Running the test results in:
java.lang.AssertionError:
0 - Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface org.springframework.data.domain.Pageable
java.lang.IllegalStateException: No primary or default constructor found for interface org.springframework.data.domain.Pageable
The method getStructuresByDocumentId expects a Pageable object as its second argument. Changing the annotation #SpringBootTest to
#WebMvcTest(MyController.class)
#EnableSpringDataWebSupport
Doesn't solve the problem. Any ideas, how to solve this issue?
you used "myService" in your setupDocumentWithStructures whereas your #MockBean is myServiceImpl.......I think you meant to use myServiceImpl in setupDocumentWithStructures
That's how it can work
#Before
public void setupOrInit() {
this.mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setControllerAdvice(new ErrorRequestInterceptor(tracer))
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build();
}
I was having the same problem and fixed setting a new mockMvc like this
#Before
public void before() {
MockitoAnnotations.initMocks(this);
target.setMockMvc(MockMvcBuilders.standaloneSetup(myController)
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build());
}
I am not using #SpringBootTest as you are, but I think in this case it does not matter. Below is my entire (redacted) code.
#RunWith(SpringRestPactRunner.class)
#Provider("my-provider")
#PactBroker(url = "https://pact-broker.my-compnay.com")
public class MyControllerProviderContractTest {
#TestTarget
public final MockMvcTarget target = new MockMvcTarget();
#Mock
private MyService myService;
#InjectMocks
private MyController myController = new MyController();
#Before
public void before() {
MockitoAnnotations.initMocks(this);
target.setMockMvc(MockMvcBuilders.standaloneSetup(myController)
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build());
}
#State("my state")
public void stateForMyMethod() {
//my mocks
}
}
I hope this helps, I spend a few hours trying to solve this.
Cheers
Hi I am new to groovy unit test using mockito.I am trying to figure how to write test case for daoImpl calss without really updating or inserting in database.
below is my code.
#Component
public class TransactionDAOImpl implements TransactionDAO {
#Autowired
StringUtilities stringUtilities;
#Autowired
private TransactionRepository transactionRespository;
#Override
#Transactional
public String create(List<DepositoryTransaction> depositoryTransaction) {
List<DepositoryTransaction> dep = transactionRespository.saveAll(depositoryTransaction);
LOGGER.debug("Recieved atm transaction : {} = {}", dep);
if (dep != null && !dep.isEmpty())
return stringUtilities.SUCCESS;
else
return stringUtilities.FAILURE;
}
}
#RunWith(MockitoJUnitRunner.class) // org.mockito.runners.MockitoJUnitRunner is deprecated so use org.mockito.junit.MockitoJUnitRunner instead
public class TransactionDAOImplTest{
#InjectMocks
private TransactionDAOImpl transactionDAOImpl;
#Mock
StringUtilities stringUtilities;
#Mock
private TransactionRepository transactionRespository;
List<DepositoryTransaction> depositoryTransaction=new ArrayList<>();
#Test
public void testCreateSaveAllNullReturn(){
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(null);
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.SUCCESS); // i do not khnow if this is an enum ?
}
#Test
public void testCreateSaveAllEmptyReturn(){
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(new ArrayList<>());
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.SUCCESS); // i do not khnow if this is an enum ?
}
#Test
public void testCreateSaveAllNotEmptyAndNotNullReturn(){
DepositoryTransaction obj=new DepositoryTransaction();
depositoryTransaction.add(obj);
when(transactionRespository.saveAll(depositoryTransaction)).thenReturn(depositoryTransaction);
assertThat(transactionDAOImpl.create(depositoryTransaction)).isEqualTo(stringUtilities.FAILURE); // i do not khnow if this is an enum ?
}
}
I have an interface(Client) with two implementation classes PClient and SClient respectively.
Interface - Client
Impl class - PCleint, SClient
I have a controller in which both the impl classes are autowired using qualifier spring boot annotation. Now i need to write JUNIT mockito test case for the controller.
I am not sure how to mock the different Impl classes which has the same interface. I tried mocking in the following way but it throws null pointer exception in the stub method of the respective mocks.
#Mock
private Client pclient
#Mock
private Client sclient
How do i differentiate mocking different impl classes such that the methods of the impl classes are called. Should i do like the below.
#Mock
private PClient pclient
#Mock
private SClient sclient
It did not work for me . Either one throws null pointer exception . Please advise.
I guess the tricks are you need to use Before to stub the return value and use #InjectMocks for the controller.
Since #Mock won't return a "real" object, it just return a "mock"(or fake:P ) one. So when you call a method of this "mock" object, it won't return the actual output from your method, instead it gives back null. That's why you need to stub the return with #Before.
See my example code below:
Client Interface
public interface Client {
String someMethod();
}
Class implemented
public class PClient implements Client {
private static final String name = "PClient";
#Override
public String someMethod() {
return name;
}
}
public class SClient implements Client{
private static final String name = "SClient";
#Override
public String someMethod() {
return name;
}
}
The Client Controller
#Controller
public class ClientController {
#Autowired
private PClient pClient;
#Autowired
private SClient sClient;
public ClientController(){
}
public String executePClient(){
return this.pClient.someMethod();
}
public String executeSClient(){
return this.sClient.someMethod();
}
public String execute(Client client){
return client.someMethod();
}
}
The test case You need to add a #Before to stub the method return.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class ClientControllerTest {
#Mock
private PClient pclient;
#Mock
private SClient sclient;
#InjectMocks
private ClientController clientController;
#Before
public void setup(){
when(pclient.someMethod()).thenReturn(new PClient().someMethod());
when(sclient.someMethod()).thenReturn(new SClient().someMethod());
}
#Test
public void testPClient(){
String result = clientController.executePClient();
assertEquals("PClient",result);
}
#Test
public void testSClient(){
String result = clientController.executeSClient();
assertEquals("SClient",result);
}
#Test
public void testExecuteWithPClient(){
String result = clientController.execute(pclient);
assertEquals("PClient",result);
}
#Test
public void testExecuteWithSClient(){
String result = clientController.execute(sclient);
assertEquals("SClient",result);
}
}
Result: Tests passed: 4 of 4 tests - 31ms