Mocking a function without argument containing CriteriaBuilder is it possible? - java

I think the reason why is impossible to mock criteriabuilder is because it only response to the database created in postgres. If that's not the case then how can solve this error (shown below).
class MessageRest
public List<Message> getListAll(){
logger.info("Get all messages");
return messageRepository.getAll();
}
class MessageRepository
public List<Message> getAll(){
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Message> criteria = criteriaBuilder.createQuery(Message.class);
criteria.from(Message.class);
return entityManager.createQuery(criteria).getResultList();
}
class MessageRestTest
class MessageRESTTest {
#InjectMocks
MessageREST messageREST;
#Mock
private EntityManager entityManager;
#Mock
private MessageRepository messageRepository;
#BeforeEach
void Mockactivator() {
MockitoAnnotations.initMocks(this);
}
#Test
void testgetlistall()
{
List<Message> messageList = new ArrayList<>();
Message message = new Message();
messageList.add(message);
when(messageRepository.getAll()).thenReturn(messageList);
messageList = messageREST.getListAll();
}
}
The Error am getting is NullpointerException and it's comming from the last line "messageList = messageREST.getListAll()"
Thanks in advance!

It might not what you are looking for, but just in case:
Usually for such repository tests in memory databases are used, for example H2. So you can fill it with test data and then call getAll() to check if it works correctly.

Related

Mock returned value of ResultSet inside the method to be tested that implements an interface

I'm trying to mock some data with Mockito for some tests, but I can't get it to work. My problem is that the value I want to mock is the return of a call inside the method I need to test.
I have a class, MyAccessor.java (that implements a service, MyService.java) that inside has a method, getMyMethod(String value), and inside that method there is a call to the DB:
final List<MyType> results = this.jdbcTemplate.query(sqlQuery, new RowMapper<MyType>() {
#Override
public MyType mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final int fieldA = rs.getInt("column_name_1");
final int fieldB = rs.getInt("column_name_2");
final int fieldC = rs.getInt("column_name_3");
final int fieldD = rs.getInt("column_name_4");
return new MyType(fieldA , fieldB , fieldC , fieldD);
}
}, value);
There is a case where due to timeouts with the database, an empty list is returned by the rowMapper. So in that case it is not possible to do return results.get(0) because you will get an ArrayIndexOutOfBoundsException.
So I have a check:
if (!results.isEmpty()) {
return results.get(0);
} else {
return new MyType(0, 0, 0, 0);
}
Now, I want to test this particular scenario but I don't know how to mock the resultSet return so that the rowMapper returns an empty list. In my test class I have set:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { ".....", "....."})
#TestPropertySource(".....")
public class MyClassTest {
#Mock
private JdbcTemplate jdbcTemplate;
#InjectMocks
#Autowired
private MyService myService;
#Before
public void initMocks() {
MockitoAnnotations.openMocks(this);
}
#Test
public void myTestMethod() {
Mockito.when(this.jdbcTemplate.query("SELECT NULL LIMIT 0", new RowMapper<Object>() {
#Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new ArrayList<>();
}
})).thenReturn(new ArrayList<Object>());
MyType result = this.myService.getMyMethod("value");
assertEquals(0, result.getFieldA());
assertEquals(0, result.getFieldB());
assertEquals(0, result.getFieldC());
assertEquals(0, result.getFieldD());
}
}
But the test fails because the result returned is from the database instead of an empty list to test the timeout case.
I think the problem may be because I'm injecting the mock in the service interface instead of the implementation, but I wanted to know if it can be done somehow so I don't have to test the mock for each implementation of that interface.
Or maybe I am using the Mockito framework wrong and in that case, how can I test correctly?
Regads.
I think you want something more like:
#Test
public void myTestMethod() {
Mockito.when(this.jdbcTemplate.query(eq("SELECT NULL LIMIT 0"), Mockito.any(RowMapper.class))
.thenReturn(new ArrayList<Object>());
}
Reason is because when mocking, you were saying only to return the empty list if both arguments to the query is exactly as you defined. In your case, you don't care about the exact instance of RowMapper.
I have found the problem. I was injecting the mock in the interface and not in the implementation of the interface. So I had to change:
#Mock
private JdbcTemplate jdbcTemplate;
#InjectMocks
#Autowired
private MyService myService;
to:
#Mock
private JdbcTemplate jdbcTemplate;
#InjectMocks
#Autowired
private MyAccessor myAccessor;
#Autowired
private MyService myService;
And inside the test this:
MyType result = this.myService.getMyMethod("value");
to:
MyType result = this.myAccessor.getMyMethod("value");
I don't know if there is a better way to do this, without having to instantiate all the implementations that the service may have.
Regards.

How to mock joins in queryDsl (jpa + mockito)?

Given the queryDsl code that selects from entities by joining them
#Repository
#RequiredArgsConstructor
public class BlahRepository {
private final JPAQueryFactory jpaQueryFactory;
public List<YyzPerEntity> getYyzPerById(Long id) {
final QYyzPerEntity n = YyzPerEntity;
final QDufEntity d = dufEntity;
final QWofEntity g = wofEntity;
return jpaQueryFactory
.selectFrom(n)
.leftJoin(d)
.on(n.pLnr.eq(d.dufEntityPK.dofx))
.leftJoin(g)
.on(d.wof.getID().eq(g.Id))
.where(g.Id.eq(Id))
.fetch();
}
I want to mock the join part like:
#Mock private JPAQueryFactory queryFactory;
private JPAQuery queryMock;
#InjectMocks private BlahRepository blahRepository;
#Test
void byId() {
// arrange
queryMock = mock(JPAQuery.class);
when(queryFactory.selectFrom(QYyzPerEntity.yzPerEntity))
.thenReturn(queryMock);
// how to mock joins here... ?
when(queryMock.fetch()).thenReturn(List.of(QYyzPerEntity.yzPerEntity));
// act
List<YyzPerEntity> yyzPerById =
blahRepository.getYyzPerById(123L);
// assert
assertThat(yyzPerById).isNotNull();
any ideas what I could try?
Error that I get is:
java.lang.NullPointerException: Cannot invoke com.querydsl.jpa.impl.JPAQuery.on(...) because the return value of com.querydsl.jpa.impl.JPAQuery.leftJoin(com.querydsl.core.types.EntityPath) is null
Is it possible at all or cannot be mocked ?
The easiest way to mock builder API's, like for example JPAQuery, is to use Answers.RETURNS_SELF as default stub.
For example, use the following to instantiate your queryMock:
#Mock(answer = Answers.RETURNS_SELF) JPAQuery queryMock;

How to write a mocked unit test for a db insert method in Springboot REST API?

I have a REST API written in Spring Boot.
Now I want to create unit tests with JUnit and Mockito that mock the database operations.
Here is the endpoint that inserts a new customer to the db.
#RestController
public class CustomerController {
#Autowired
private CustomerRepository customerRepository;
#PostMapping(value="/customers", produces = "application/json")
public ResponseEntity<Customer> addCustomer(#RequestBody Customer customer){
Customer newCustomer = customerRepository.save(customer);
return new ResponseEntity<Customer>(newCustomer, HttpStatus.OK) ;
}
Test:
#Test
public void testAddCustomer() {
Customer customer = Mockito.mock(Customer.class);
customer.setIdCustomer(1L);
customer.setName("Pete");
customer.setAge(35);
customer.setEmail("pete#test.com");
when(customerRepository.save(customer)).thenReturn((Customer) Stream.of(customer));
CustomerController customerController = new CustomerController();
ResponseEntity<Customer> respCustomer = customerController.addCustomer(customer);
assertTrue(respCustomer.getBody().getIdCustomer() != null);
}
I'm getting a null pointer exception on the following line:
when(customerRepository.save(customer)).thenReturn((Customer) Stream.of(customer));
Use
#Mock
private CustomerRepository customerRepository
in your test and configure the repository using mockito API
it should be something like this
#Test
public void testFindTheGreatestFromAllData() {
DataService dataServiceMock = mock(DataService.class);
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 24, 15, 3 });
SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceMock);
int result = businessImpl.findTheGreatestFromAllData();
assertEquals(24, result);
}

How to write unit tests for EntityManager transaction?

I am trying to write a unit test for a existing function that updates a value of a DB field using EntityManager. My unit test should verify that the class updates the value correctly. The current code looks like this:
public class MyClass {
MyClass(EntityManager em) {
this.em = em;
}
void updateValue() {
em.getTransaction().begin();
TypedQuery query = em.createQuery("select a from ...", MyResult.class);
List<MyResult> results = query.getResultList();
MyResult result = results.get(0);
result.setInterestingValue(1);
em.getTransaction().commit();
}
}
My current approach for the unit testing:
#Mock EntityManager em;
#Mock TypedQuery query;
publid void test() {
MyClass myClass = new MyClass(em);
MyResult result = new MyResult();
ArrayList<MyResult> resultList = new ArrayList<>();
resultList.add(result);
when(em.getTransaction()).thenReturn(mock(EntityTransaction.class));
when(em.createQuery(anyString(), any())).thenReturn(query);
when(query.getResultList()).thenReturn(resultList);
myClass.updateValue();
assertEquals(1, result.getInterestingValue());
}
My unit test above verifies that the MyResult instance is updated. However, it doesn't verify that the value is actually updated through EntityManager. In other words, I'd like to test if EntityManager is correctly used in the existing code. For example, even if I call commit() before setInterestinvValue(1), my test will still pass. Is there a good way to test it?
As commented above, if you use mockito, the solution will be - use inOrder():
MyResult result = mock(MyResult.class);
EntityTransaction transaction = mock(EntityTransaction.class)
inOrder.verify(result).setInterestingValue(1);
inOrder.verify(transaction).commit();

Criteria Query Mockito unit test - NullPointerException

I have a method that i'm trying to test using mockito. Below is the method i'm trying to test. I'm getting a null pointer exception when I run my test. I'm mocking Root but at accountEntity.get I'm getting null pointer. What am I missing here?
public List<AccountEntity> createCriteriaQuery(final List<String> accountIdList,
final MultiValueMap<String, String> allRequestParams) {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<AccountEntity> cq = cb.createQuery(AccountEntity.class);
final Root<AccountEntity> accountEntity = cq.from(AccountEntity.class);
final Join<AccountEntity, PlanEntity> account = accountEntity.join(AccountEntity_.planEntity);
final List<Predicate> predicates = new ArrayList<Predicate>();
//Getting null pointer at the below call.
**predicates.add(accountEntity.get(AccountEntity_.id).in(accountIdList));**
/*remaining code here/
below is my test.
#InjectMocks
private AccountsDAO accountsDao;
#Mock
EntityManagerFactory entityManagerFactory;
#Mock
EntityManager entityManager;
#Mock
CriteriaBuilder cb;
#Mock
CriteriaQuery<AccountEntity> cq;
#Mock
Root<AccountEntity> rootAccountEntity;
#Test
public void canGetAllAccountsInfo() {
when(entityManagerFactory.createEntityManager()).thenReturn(entityManager);
when(entityManager.getCriteriaBuilder()).thenReturn(cb); when(cb.createQuery(AccountEntity.class)).thenReturn(cq);
when(cq.from(AccountEntity.class)).thenReturn(rootAccountEntity);
//Null pointer in the actual method call
accountEntityList = accountsDao.createCriteriaQuery(accounIdList, allRequestParams);
}
I would guess that accountEntity.get(AccountEntity_.id) resolves to null since you have not added any when(...).thenReturn(...) for the mocked accountEntity object in play.
I was missing this statement
when(accountEntity.get(AccountEntity_.id)).thenReturn(path);
I added this in the test class
#Mock
Path<String> path;
In the actual code for this to pass
predicates.add(accountEntity.get(AccountEntity_.id).in(accountIdList))
I need this
when(accountEntity.get(AccountEntity_.id)).thenReturn(path);

Categories