Data can't fetch from db - mockito - java

I am using the Mockito framework for my jUnit testing.
I am not able to fetch data from the database. Fetches null or empty from the db. Not sure how can I mock the entityManager.
public class AppServiceTest {
#Mock
private EntityManager entityManager;
#Mock
DataSource mockDataSource;
#Mock
Connection mockConn;
#Mock
PreparedStatement mockPreparedStmnt;
#Mock
ResultSet mockResultSet;
#Mock
private Query query;
#Test
public void testGetAllDc() throws NamingException {
AppDataService appDataService = Mockito.mock(AppDataService.class);
List<String> customResults = new ArrayList<String>();
//customResults = ....
System.out.println("**RESULTS**"+appDataService.getAllDc()); // here it is printed as []
Mockito.when(appDataService.getAllDc()).thenReturn(customResults);
}
}
AppDataService.java:
#Stateless
public class AppDataService{
#PersistenceContext
EntityManager entityManager;
public List<Object> getAllDc() {
try {
Query query = entityManager.createQuery("myQuery");
List<String> allDc= query.getResultList();
}
//......
}
Update:
Its observed that the mock values can be detected for entityManager as Mock for EntityManager, hashCode: 5425710. But entityManager.getCriteriaBuilder() or whatever entityManager.get....() are getting null in the AppDataService class .

In your test, you create a mock AppDataService appDataService = Mockito.mock(AppDataService.class);.
In order to test this class, you must not mock it. Either create it using new AppDataService() or let mockito do that for you (#InjectMocks)
To initialize the mocks or the class-under-test you may do this by using annotations and either use the mockito runner:
#RunWith(MockitoJunitRunner.class)
public class AppServiceTest {
#InjectMock
private AppService appService;
#Mock
private EntityManager entityManager;
or
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
Further, you mocked entitymanager, therefore all of it's methods are stubbed and return no values (null) per default on any method call.
If you expect the createQuery("myQuery") invocation to return something, you should stub it properly after mock creation/injection in the setup method.
#Before
public void setup() {
//...
when(entityManager.createQuery(eq("myQuery"))).thenReturn(query);
//OR
when(entityManager.createQuery(anyString())).thenReturn(query)
If it doesn't matter what the mocks return as long as it is not null, you may initialize the mocks using
#Mock(answer = Answers.RETURNS_DEEP_STUBS)) //OR #Mock(answer = Answers.RETURNS_MOCKS)
private EntityManager entityManager;
So the whole test should look like
#RunWith(MockitoJunitRunner.class)
public class AppServiceTest {
#Mock(answer = Answers.RETURNS_DEEP_STUBS))
private EntityManager entityManager;
#Mock
private Query query;
...
#InjectMocks
private AppDataService appDataService;
#Test
public void testGetAllDc() throws NamingException {
//arrange
List<String> customResults = new ArrayList<String>();
//TODO populate customResults
when(entityManager.createQuery("myQuery")).thenReturn(query);
when(query.getResultList()).thenReturn(customResults);
//act
System.out.println("**RESULTS**"+appDataService.getAllDc());

You don't need to mock appDataService if you want to test it. This field should be annotated with #InjectMocks.
#InjectMocks
private AppDataService appDataService = new AppDataService();
What you need to mock is entityManager.createQuery and query.getResultList methods.
Query queryMock = mock(Query.class);
when(entityManager.createQuery(anyString())).thenReturn(queryMock);
when(query.getResultList()).thenReturn(customResults);
After taht you can call appDataService.getAllDc() in your test and check the results.

Related

Test EntityManager with JUnit and Mockito

I have tried to test the following class, but I have been unsuccessful.
#PersistenceContext
private EntityManager em;
#Transactional
public int sendToTableOne()
{
return em.createNativeQuery("INSERT INTO TABLE_ONE"
+ " SELECT * FROM TABLE_TWO")
.executeUpdate();
}
How can I test this class?
I'm using JUnit Jupiter on Spring framework.
I don't know if it's a good solution, but I obtain 100% coverage.
#Mock
EntityManager entityManager;
#Mock
Query query;
#InjectMocks
ThSwapDaoImpl daoImpl;
#BeforeEach
void setUp() throws Exception {
}
#Test
void test() {
when(entityManager.createNativeQuery(anyString())).thenReturn(query);
when(query.executeUpdate()).thenReturn(1);
assertEquals(daoImpl.sendToHistorical(), 1);
}

Java - Spring and Mockito - Mocking a constructor parameter that is not a field in class?

I have the following Spring component that I am trying to unit test:
#Component
public class OrderService {
private final DatabaseConnection dbConnection;
private final String collectionName;
#Autowired
public OrderService(
DatabaseConnection dbConnection,
DatabaseConfig databaseConfig) {
this.dbConnection = dbConnection;
this.collectionName = databaseConfig.getCollectionName();
}
//methods etc...
}
The DatabaseConfig class is as follows:
#ConfigurationProperties(prefix = "database")
#ConstructorBinding
public class DatabaseConfig {
//methods etc...
}
I am trying to inject mocks in my OrderService class as follows:
#RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
#InjectMocks
OrderService orderService;
#Mock
DatabaseConnection dbConnection; // working as expected
#Mock
DatabaseConfig databaseConfig; // giving null pointer
#Mock
DatabaseCollectionConfig databaseCollectionConfig;
#BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
}
When I run my test class I get:
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate #InjectMocks field named 'OrderService' of type 'class com.my.package.OrderService'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
The issue is that in the OrderService constructor when I debug this line is coming as null:
this.collectionName = databaseConfig.getCollectionName();
How can I correctly mock databaseConfig.getCollectionName() to solve the null issue?
No need to use #InjectMock annotation because you are using constructor based injection in your service class. Please rewrite your test case like this and try again.
#RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
OrderService orderService;
#Mock
DatabaseConnection dbConnection; // working as expected
#Mock
DatabaseConfig databaseConfig; // giving null pointer
#Mock
DatabaseCollectionConfig databaseCollectionConfig;
#BeforeEach
public void setup(){
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
orderService = new OrderService(dbConnection, databaseConfig);
}
}
You can try to create a mock for that method and create an object instance instead of using the InjectMocks annotation.
#RunWith(MockitoJUnitRunner.class)
class OrderServiceTest {
OrderService orderService;
#Mock
DatabaseConnection dbConnection; // working as expected
#Mock
DatabaseConfig databaseConfig; // giving null pointer
#Mock
DatabaseCollectionConfig databaseCollectionConfig;
#BeforeEach
public void setup() {
(...)
when(databaseConfig.getCollections()).thenReturn(databaseCollectionConfig);
when(databaseCollectionConfig.getCollectionName()).thenReturn("myCollection");
orderService = new OrderService(dbConnection, databaseConfig);
}
Mock behavior, not values. An #ConfigurationProperties class is just a container for data; it doesn't (generally speaking) do anything. Create a real one with new using your test values (e.g., setCollections(testDatabaseCollectionConfig)).

#InjectMocks is not injecting the the list dependency, which is a #Spy

Servcice.java (class to test)
class Service {
#Autowired
private List<Metric> dependency1;
#Autowired
private Executor dependency2;
}
Metric.java : interface
interface Metric{
public void fetchMetric();
}
class Metric1 implements Metric{
public void fetchMetric() {}
}
class Metric2 implements Metric{
public void fetchMetric() {}
}
ServiceTest.java : (test class)
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Spy
private List<Metric> dependency1;
#Mock
private Executor dependency2;
#InjectMocks // class under test // this has above two as their dependencies.
Service service;
#Mock
private Metric1 metric1;
#Mock
private Metric2 metric2;
#BeforeEach
void setUp() {
// intializing the spy object list with mocks.
this.dependency1 = Arrays.asList(metric1,
metric2
);
}
#Test
void someTest() {
// here in debug mode I can see that `dependency1` as a **spy** and 'dependency1' present in the 'Service' are different, though they should be same.
}
}
Why #InjectMock is not able to Inject a #Spy List dependencies in the Service class object? Am I missing something here.
dependency1 as a spy and dependency1 present as a part of the Service are shown as two different objects on the de-bugger and making the test cases fail. I thought they should be the same.
Should we not initialise the Spies in #BeforeEach method ?
The problem is you use #ExtendWith(MockitoExtension.class) to tell mockito to instantiate your #Mocks #Spy and #InjectMocks. So after Mockito does this you change the field ServiceTest.dependency1 to be a list.
But since Mockito instantiated your CUT with the annotated dependencies, it is not updated when you change the ServiceTest.dependency1.
I would recommend to change Service to have a constructor so you can use the recommended constructor Injection.
That way you can make your test like this:
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Mock
private Executor dependency2;
Service service;
#Mock
private Metric1 metric1;
#Mock
private Metric2 metric2;
#BeforeEach
void setUp() {
// intializing the spy object list with mocks.
service = new Service(Arrays.asList(metric1,metric2), dependency2);
}
}
If you want the list to be a spy, I would do something like this:
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#InjectMocks
private Service service;
#Mock
private Executor dependency2;
#Spy
private List<Metric> dependency1;
#Test
void test() {
// you can define what to return when there is a method call on the spy dependency1
Metric metric1 = mock(Metric.class);
Metric metric2 = mock(Metric.class);
when(dependency1.get(0)).thenReturn(metric1);
when(dependency1.get(1)).thenReturn(metric2);
service.test();
}
}
One way to handle it:
Remove #Spy and use #Mock on dependency1.
And you will need to handle the List w.r.t. the testcase like:
Mockito.doReturn(metric1).when(dependency1).get(ArgumentMatchers.anyString());

how to mock a mehod using spring boot SpringJUnit4ClassRunner where mongo tamplate is used where the method contains static call

i am sharing a method code which contains static method call.
public List<String> getTestContent() {
DistinctIterable<String> distinctIterable = mongoTemplate.getCollection("test-doc").distinct("testcontent",String.class);
return StreamSupport.stream(distinctIterable.spliterator(),false).collect(Collectors.toList());
}
i need to mock this method which i shared. I have tried lot of approach but getting null pointer
I have written test for the method you provided.
#RunWith(SpringJunit4ClassRunner.class)
public class MyTestClass
{
#MockBean
private MongoTemplate mongoTemplate;
#MockBean
private MongoCollection<Document> mongoCollection;
#MockBean
private DistinctIterable<String> distinctIterable;
#InjectMocks
private ServiceImpl service;
#Before
public void setUp()throws Exception{
MockitoAnnotations.openMocks(this);
}
public void testGetTestContent(){
List<String> list = new ArrayList<>();
list.add("test1");
list.add("test2");
Spliterator<String> spliterator = list.spliterator();
PowerMockito.when(mongoTamplate.getCollection(Mockito.eq("test-doc"))).thenReturn(mongoCollection);
PowerMockito.when(mongoCollection.distinct(Mockito.eq("testcontent"),Mockito.eq(String.class))).thenReturn(distinctIterable);
PowerMockito.when(distinctIterable.spliterator()).thenReturn(spliterator);
Assert.assertEquals(2,service.getTestContent().size());
}
}
Note: You can also use PowerMockito.doReturn(..).when() if you don't want to check the type of value returned

Unable to mock JdbcTemplate in testing spring boot service

In the test case for service,I am unable to resolve dependency of dao class and JdbcTemplate.
public class TestPromotionUsingJunit {
#InjectMocks
private ItemService itemService;
#Mock
private ItemDAOImpl itemDAOImpl;
#Mock
private JdbcTemplate jdbcTemplate;
#Before
public void setupMock() {
MockitoAnnotations.initMocks(this);
itemService = new ItemService();
}
#Test
public void testFindMax() {
Product pro1 = new Product();
pro1.setPluCode("4900692627408");
pro1.setCategoryNo("2");
pro1.setCategoryName("Women");
pro1.setProductName("T-Shirt10163");
pro1.setColor("CY");
pro1.setSize("32");
BigDecimal b1 = new BigDecimal(94.00);
BigDecimal b2 = new BigDecimal(8);
pro1.setPrice(b1);
pro1.setTax(b2);
Product pro2 = new Product();
pro2.setPluCode("4900692627408");
assertEquals(pro1.getPrice(), itemService.getItem(pro1));
}
}
Here ItemService should return product object but it returns null. Due to internally unable to solve dependency.
#InjectMocks creates a mock instance of itemService, but then
itemService = new ItemService();
creates a real instance and throws the mock away. In setupMock(), after itemService is constructed, try adding the equivalent of this:
itemService.setItemDao(itemDAOImpl);
So you'll have a real ItemService which uses a mock DAO.
Then in testFindMax() configure the DAO to return pro1, something like this:
when(itemDAOImpl.getItem(...)).thenReturn(pro1);

Categories