Hot questions for Using Mockito in hibernate

Question:

This is my class which need to be tested:

@Repository
@Transactional
public class ProductDAOImpl implements ProductDAO {

private static final Logger logger = Logger.getLogger(ProductDAOImpl.class);

@Autowired
private SessionFactory hibernateSessionFactory;


@Override
public ProductDTO getProduct(String isbn) throws ProductException {
    ProductDTO productDTO = new ProductDTO();
    Product product = getProductFromDb(isbn);
    BeanUtils.copyProperties(product, productDTO);
    return productDTO;
}

private Product getProductFromDb(String isbn) throws ProductException{
    Session session = this.hibernateSessionFactory.getCurrentSession();


    String hql = "FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13";
    Query query = session.createQuery(hql);
    query.setParameter("isbn13",isbn);


    List<Product> productList = query.list();  // Want to mock this call
    if(productList.size() ==1)      
        return productList.get(0);
    else if(productList.size() >1)
        // throw new ProductException("Cannot return product. Multiple products found.", HttpServletResponse.SC_NOT_FOUND);
        throw new ProductException("Cannot return product. Multiple products found.");
    else if(productList.size() == 0){
        throw new ProductException("Cannot return product. No products found.");
    }
    return null;

}

I want to mock the query.list() method. This is what I have tried so far but getting exception: Type 'SessionFactory' is an interface and it cannot be spied on.

@RunWith(MockitoJUnitRunner.class)
public class TestProductDaoImpl {

@Spy
private SessionFactory hibernateSessionFactory;
@InjectMocks
private ProductDAOImpl productDAOImpl;

@Test
public void testGetProduct() throws ProductException {

    Session session = this.hibernateSessionFactory.getCurrentSession();

    String hql = "";
    Query query = session.createQuery(hql);
    Query spy = Mockito.spy(query);
    List<Product> productList = getProductList();
    doReturn(productList).when(spy).list();

    productDAOImpl.getProduct("abc");


}

I can mock the getProductFromDb(). But in that case there is no need to write a test case for that as the maximum part of the class is getting mocked.


Answer:

In my opinion there are two approach:

First: Create mock on SessionFactory like this

@Mock
private SessionFactory hibernateSessionFactory;

@Before
public void beforeTest(){
    MockitoAnnotations.initMocks(this);
}

@Test
public void testGetProduct() throws ProductException {
     //then mock all you need from hibernateSessionFactory
     Session session = Mockito.mock(Session.class);
     Query query = Mockito.mock(Query.class);

     Mockito.when(hibernateSessionFactory.getCurrentSession()).thenReturn(session);
     Mockito.when(session.createQuery("FROM com.esp.dao.entity.Product P WHERE P.isbn13 = :isbn13")).thenReturn(query);

     List<Product> productList = new ArrayList<>(1);
     Mockito.when(query.list()).thenReturn(productList);

Second: You should create instance of SessionFactory

private SessionFactory hibernateSessionFactory;

@Before
public void beforeTest(){
    hibernateSessionFactory = Mockito.spy(new ConstructorForSessionFactory ());
}

Question:

I have some hibernate methods and when i test them, mockito always return null instead of expected value

This is my hibernate method

@Autowired
private SessionFactory sessionFactory;

public StudentDAO() {

}
public List<StudentDetail> listStudentDetail() {
    String hql = "Select new " + StudentDetail.class.getName() //
            + "(s.studentid,s.name,s.address) " //
            + " from " + Student.class.getName() + " s ";
    Session session = this.sessionFactory.getCurrentSession();
    Query<StudentDetail> query = session.createQuery(hql, StudentDetail.class);
    List<StudentDetail> list =null;
    list = query.getResultList();
    return list;
}

And this is my test method

@Mock
SessionFactory sessionFactory;
@Mock
Query query;
@Mock
Session session;
@Mock
List<StudentDetail> list;
@InjectMocks
private StudentDAO studentDAO ;

// Test get method

@Test
public void getListStudentTest() {
    StudentDetail sd1 = new StudentDetail(1, "A", "X");
    Mockito.when(query.getResultList()).thenReturn(list);
    Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session);
    Mockito.when(session.createQuery(ArgumentMatchers.anyString())).thenReturn(query);
    Mockito.verify(sessionFactory.getCurrentSession());
    Mockito.verify(session.createQuery(ArgumentMatchers.anyString(),ArgumentMatchers.anyObject() ));
    Mockito.verify(query.getResultList());

    Assert.assertEquals(sd1, studentDAO.listStudentDetail().get(0));
}

When i run my web app, studentDAO.listStudentDetail() return true value normally but in test method its always return null


Answer:

Here

Assert.assertEquals(sd1, studentDAO.listStudentDetail().get(0));

the studentDAO.listStudentDetail() returns a mock list. You didn't mock its .get method. Thus it returns null by default. You should modify your assertEquals check:

Assert.assertEquals(list, studentDAO.listStudentDetail());

(You don't need the sd1 object at all)


Also you are not using verify properly. You should do like this:

Mockito.verify(sessionFactory).getCurrentSession();
Mockito.verify(session).createQuery(ArgumentMatchers.anyString());
Mockito.verify(query).getResultList();

(note the closing parenthesis before .)

Question:

I am working on a SPringBoot+Hibernate+REST project using Mysql DB. I want to know how I can Unit Test the below class. I have been told that Mocking is the best way to go about it. I think this is related to Database Mock Testing. I have no clue even after researching a lot online. Can someone guide me how I should test it. If I have DAO classes in my project which use thse db connections, do I still need to test the below Class? I even have RestController Class which needs to be tested. Please guide me how I should go ahead with this. I am a beginner.

DBConfiguration.Java

package com.youtube.project.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

@PropertySource(value = { "classpath:application.properties" })
@Configuration
@EnableTransactionManagement
public class DBConfiguration {

    @Value("${jdbc.driverClassName}")
    private String driverClass;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Value("${hibernate.dialect}")
    private String dialect;

    @Bean
    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource(url,username,password);
        dataSource.setDriverClassName(driverClass);
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
        factory.setDataSource(getDataSource());
        factory.setHibernateProperties(hibernateProperties());
        factory.setPackagesToScan(new String[] {"com.youtube.project"});
        return factory;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", dialect);
        properties.put("hibernate.hbm2ddl.auto", "update");
        properties.put("hibernate.show_sql", "true");
        properties.put("hibernate.format_sql", "true");
        return properties;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory factory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(factory);
        return transactionManager;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
          LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
          em.setDataSource(getDataSource());
          em.setPackagesToScan(new String[] { "com.youtube.project.model" });     
          JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
          em.setJpaVendorAdapter(vendorAdapter);
          return em;
       }
} 

Answer:

I want to know how I can Unit Test the below class

Well, it is kinda complicated because your configuration class actually makes connections to the database so this class is not actually very desirable for "Unit Testing" per-se.

Because UNIT TESTING is a level of software testing where individual units/ components are tested (unit is the smallest testable part of your application). It usually has one or a few inputs and usually a single output.

IMHO I would put this as Integration testing because you would need to connect to a database.

How to approach testing this:

TL;DR - Don't bother writing an explicit test for this class.

By running a @SpringBootTest on your main class, your class should get tested as a side effect.

Explanation:

It makes little sense to test this class explicitly because you will basically test:

  • Have the beans been created
  • Are the @Value fields populated with values
  • Is the connection to the database established

From these 3 things, only point #3 is valid to test, the first two are tested by Spring developers when they were writing the framework. That being said, connecting to the database is more of an integration test than a unit test. If you want to test that, you can use an in-memory database like H2, it can be configured to run on tests only.

I have DAO classes in my project which use thse db connections, do I still need to test the below Class? I even have RestController Class which needs to be tested.

Spring has a great support for testing application slices (parts of your app, e.g: one class at a time or a class + it's dependencies).

Specifically:

  • for DAO class, check out @DataJpaTest and TestEntityManager class.
  • For controller classes, use @WebMvcTest and MockMvc class.

These things are designed to make your testing easier with spring boot. For some basic info, you can check out this article.

Hope this helps

Question:

Spring Version: 3.2.4.RELEASE and 3.2.9.RELEASE

Mockito Version: 1.8.5

I've been trying to introduce H2 tests to an old project for integration testing, and I've been running into a few issues. Due to the way transactions were propagating, I needed to mock out an autowired class. I've done this before, but I'm now running into severe problems. The following error message is being thrown when initialising the test:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.stuff.XMLITCase': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'TheProcessor' must be of type [com.stuff.XMLBatchFileProcessor], but was actually of type [$Proxy118] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:307)

Diving into this a bit deeper, it turns out the the bean is in-fact a proxy. If we check the AbstractBeanFactory (round line 239), we can see the proxy:

sharedInstance = {$Proxy117@7035} "com.stuff.XMLBatchFileProcessor@66c540d0" h = {org.springframework.aop.framework.JdkDynamicAopProxy@7039}

The only problem is, I've no clue where this is coming from. I've gone over the config and dependencies, and can't find anywhere that this should be happening.

Project Setup

Unfortunately I can't give a sample project for this, but I'll go over my test configuration. I have a root class that I extend for the tests:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/spring-test-context.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public abstract class AbstractIntegrationTest {
}

This simply loads in some spring config and rolls back the transactions after each test.

The spring config is nothing strange either, though there is one difference between my other module and this one. This is the transaction manager and session factory:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>

<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
...
</bean>

In my other module, I'm using an entityManagerFactory, and a different transaction manager:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>

The actually class has some autowired fields, and the usual @Service annotation:

@Service(value = "TheProcessor")
public final class XMLBatchFileProcessor extends BatchFileProcessor implements IXMLBatchProcessor {

Finally, the actual test is as follows:

public class XMLITCase extends AbstractIntegrationTest {

    @Resource(name = "TheProcessor")
    @InjectMocks
    private XMLBatchFileProcessor xmlProcessor;

    @Mock
    private ProcessHelper processHelper;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test() throws Exception {
        Assert.assertNotNull(xmlProcessor);
    }

}

If I replace the XMLBatchFileProcessor with the interface and autowire the field, then there aren't any problems compiling. Mockito, however, never replaces the autowired bean with the mocked object. If it did, then I wouldn't bother with the @Resource annotations and naming the service, thus avoiding the Proxy issue.

Any assistance on this would be appreciate. I'll be focusing on the session factory and the differences there, but it's quite possible that I'm missing something else entirely.

EDIT

Going on Sotirios' comment, I had another look this morning and indeed had missed that the xmlProcessor has a @Transactional annotation, thus meaning that the class needs to be proxied. If I remove the final declaration and let CGLib enhance it, then Mockito does replace the bean when initMocks(this) this called. When a method is called, however, CGLib seems to replace all the beans with Spring enhanced versions, hence overwriting the Mockito version.

What is the correct way to use both Mockito and Spring in an integration test for a class with @Transactional annotations?


Answer:

Alright, once I realised that the class was being proxied due to the @Transactional annotation, the solution to the problem became clearer. What I needed to do was unwrap the proxy, and set the mocked object directly on that:

So in my AbstractIntegrationTest:

/**
 * Checks if the given object is a proxy, and unwraps it if it is.
 *
 * @param bean The object to check
 * @return The unwrapped object that was proxied, else the object
 * @throws Exception
 */
public final Object unwrapProxy(Object bean) throws Exception {
    if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
        Advised advised = (Advised) bean;
        bean = advised.getTargetSource().getTarget();
    }
    return bean;
}

Then in my @Before:

@Mock
private ProcessHelper processHelper;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);

    IXMLBatchProcessor iXMLBatchProcessor = (IXMLBatchProcessor) unwrapProxy(xmlProcessor);
    ReflectionTestUtils.setField(iXMLBatchProcessor , "processHelper", processHelper);
}

This left all the @Autowired classes intact, while injecting the correct mocked object.

Question:

I would have a problem with the junit tests with mockito. when I try to verify a service I get the error: "Actual invocation has different arguments"

Model:

@Entity
@Table(name = "projects")
public class Project {

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    @Column(name = "id_project")
    private Long id;

    @Column(name = "project_name")
    private String name;

    @JsonInclude(value = Include.NON_NULL)
    @Column(name = "project_language")  
    private String language;

    @Temporal(TemporalType.DATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    @Column(name = "start_date")
    private Date start_date;

    @Temporal(TemporalType.DATE)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    @Column(name = "end_date")
    private Date end_date;

    @Transient
    @JsonIgnoreProperties
    private Long id_user;

    @ManyToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_content_manager")
    private User contentManager;

    @Transient
    private Long id_license;

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_license")
    private License license;

    @OneToMany
    @LazyCollection(LazyCollectionOption.FALSE)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinTable(name = "team", joinColumns = { @JoinColumn(name = "id_project") }, inverseJoinColumns = { @JoinColumn(name = "id_user") })
    private List<User> team;

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "id_policy")
    private ProjectPolicy policy;

    @OneToMany
    @LazyCollection(LazyCollectionOption.FALSE)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinTable(name = "project2tag", joinColumns = { @JoinColumn(name = "id_project") }, inverseJoinColumns = { @JoinColumn(name = "id_tag") })
    private List<Tag> tags = new ArrayList<Tag>();
...

Controller:

@RequestMapping(value = "/", method = RequestMethod.PUT, consumes = "application/json" , produces = "application/json")
    public @ResponseBody ResponseEntity<BaseModel> edit( @RequestHeader(value="Authorization") String token, @RequestBody Project project, Locale locale) throws ParseException{
        if(!SecurityUtil.validateToken(token)) {
            return new ResponseEntity<BaseModel>(new BaseModel("error", MessageHandler.returnMessage("invalid_token", locale)), HttpStatus.UNAUTHORIZED);
        }
        if(project.getId() == null ) {
            return new ResponseEntity<BaseModel>(new BaseModel("error", "Bad request"), HttpStatus.BAD_REQUEST);
        }

        Project projecttmp = projectDao.findById(project.getId());
        if( projecttmp != null) {
            project.setContentManager(projecttmp.getContentManager());
            project.setLicense(projecttmp.getLicense());
            project.setPolicy(projecttmp.getPolicy());
            project.setTags(projecttmp.getTags());
            project.setTeam(projecttmp.getTeam());
            projectDao.editProject(project);
            return new ResponseEntity<BaseModel>(new BaseModel("ok", "ok"), HttpStatus.OK);
        }

        return new ResponseEntity<BaseModel>(new BaseModel("error", MessageHandler.returnMessage("internal_error", locale)), HttpStatus.INTERNAL_SERVER_ERROR);
    }

and the test with failure:

@Test
    public void updateProject() throws Exception{
        Project project = new Project();
        project.setId(new Long(22));

        when(projectService.findById(anyLong())).thenReturn(project);

        String json = mapper.writeValueAsString(project);

        logger.info(json);

        doNothing().when(projectService).editProject(any(Project.class));

        mockMvc.perform(put("/project/")
                .header("Authorization", TOKEN)
                .accept(MediaType.APPLICATION_JSON)
                .content(json)
                .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andDo(MockMvcResultHandlers.print());

        verify(projectService, times(1)).findById(eq(project.getId()));
        verify(projectService, times(1)).editProject(eq(project));
    }

When i can try to run the test the result is "Actual invocation has different arguments" someone who can help me?


Answer:

Mockito.eq() compares using .equals() method. You should override this method (and hashCode as well) in Project class, and make comparison by id. For example:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Project project = (Project) o;

    return getId() != null ? getId().equals(project.getId()) : project.getId() == null;
}

@Override
public int hashCode() {
    return getId() != null ? getId().hashCode() : 0;
}

Question:

I'm working on an implementation of a DAO that have to persist an entity, but i'm stuck having to mock the beginning of the transaction.

In particular, i don't know how to mock with Mockito this call:

entityManager.getTransaction().begin();

Answer:

You can mock entityManager and make it returning transaction mock.

public class DaoTest {

  EntityManager entityManager = Mockito.mock(EntityManager.class);
  EntityTransaction transaction = Mockito.mock(EntityTransaction.class);
  Dao dao = new MyDao();

  @Test
  void whenSave_thenBeginTransaction(){
    when(entityManager.getTransaction()).thenReturn(transaction);
    dao.save(new MyObject());
    verify(transaction).begin();
  }            
}

Question:

I'm learning Mockito and I want the mock the Hibernate session and Hibernate criteria as used in the method doubleCountAnimal(Session) :

public class ZooKeeper {

  public int doubleCountAnimal(Session session) {
    long rowCount = (long) session.createCriteria(Animal.class)
        .setProjection(Projections.rowCount())
        .uniqueResult();
    return (int) rowCount * 2;
  }
}

And here's my unit test, written with Mockito :

public class ZooKeeperMockTest {

  private static final Animal[] animals = new Animal[] {new Animal("Cat"), new Animal("Dog")};
  private Session mockedSession;
  private Criteria mockedCriteria;

  @Before
  public void setUp() {
    mockedSession = Mockito.mock(Session.class);
    mockedCriteria = Mockito.mock(Criteria.class);

    Mockito.reset(mockedSession, mockedCriteria);
    // mock session
    Mockito.when(mockedSession.createCriteria(Animal.class)).thenReturn(mockedCriteria);
    // mock criteria
    Mockito.when(mockedCriteria.setProjection(Projections.rowCount())).thenReturn(mockedCriteria);
    Mockito.when(mockedCriteria.uniqueResult()).thenReturn((Object) (animals.length * 1L));
  }

  @Test
  public void testDoubleCountAnimal() {
    ZooKeeper zooKeeper = new ZooKeeper();
    assertEquals(animals.length * 2, zooKeeper.doubleCountAnimal(mockedSession));
  }
}

However, when I run the test, I get an exception at the below line :

        .uniqueResult();

I don't understand why I'm getting this error. I think the mock for the above method uniqueResult is already done before the test. Can somebody help ?

Running io.mincongh.zoo.mockito.ZooKeeperMockTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.065 sec <<< FAILURE!
testDoubleCountAnimal(io.mincongh.zoo.mockito.ZooKeeperMockTest)  Time elapsed: 0.064 sec  <<< ERROR!
java.lang.NullPointerException
    at io.mincongh.zoo.ZooKeeper.doubleCountAnimal(ZooKeeper.java:14)
    at io.mincongh.zoo.mockito.ZooKeeperMockTest.testDoubleCountAnimal(ZooKeeperMockTest.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)


Results :

Tests in error: 
  testDoubleCountAnimal(io.mincongh.zoo.mockito.ZooKeeperMockTest)

My question is related to the mocking framework, please do not close it as a duplicate of simple NullPointerException.


Answer:

Thanks to Jim Garrison's help in the comment, I found the error.

The error appears to be that the mocked Criteria#setProjection() is returning null instead of this to allow method chaining. I haven't worked with Mockito in years but isn't there some way of overriding the mocking to return this?

The response is yes, there's a way to do it using Mockito#anyObject in the unit test :

Mockito.when(mockedCriteria.setProjection((Projection) Mockito.anyObject()))
    .thenReturn(mockedCriteria);

Question:

I am new to Mockito and I have started to learn it. But I have some questions. Why do we need to use Mockito? As far as I know it is used to Mock(Create dummy object) and write the test cases before having actual running code. But, what if I want to test my already implemented code to check whether they are functioning properly or not. How would I test it using Mockito?

For instance, I have CRUD methods and I would like to test whether Create is functioning properly by actually inserting data in database using my Create method, similarly for others. Can we attain it using Mockito. If not, then do I need to write different testcases for them without using Mockito?


Answer:

The Mock is used to each class or service you are using. The class under test should not be Mocked. Lets assume you are connecting to a remote service which is being built by one of your engineering team, and you are not familiar with its internal functionality but you know what requests and response it returns. In that case, you can create a Mock of that Object, and defines it with set of responses returns in different situations. Each situation should get its own different test and for each response you should check separately the reaction of the code (you are working on).

Another great example is creating a limitation checks. Lets think of exception that might be thrown in some situations. You can Mock the object that will throw the Exception which is simple(~2-3 line of test code if you are using Mock) and you can check how the code you have written reacts to that Exception. Without the Mock the throwing of an exception might be really complicated thing and not so easy to use if you are not familiar with the small details. And of course the Mock enables you to be on focus of the main functionality you are checking cause it make the checking time very very small. And that is a bless when time to market is a critical thing.

Question:

I try to use Integration testing my class with JUNit, DBUnit and Hibernate.

For the initialization of the database

To simulate an isolated database, I used this tutorial.

Note that I had to create two HibernateUtil class (one (named HibernateUtils.class) based on the tutorial which allowed me to set where hibernate.test.cfg.xml is located, the other one (named HibernateSessionFactory which created the SessionFactory based on hibernate.cfg.xml )

Integration Testing

I have to test the show_Potions() method from Player.class.

show_Potions() set the potions of the player based on a query from the database. I want the test to make queries in the isolated database not the real database so I proceed that way: when the HibernateSessionFactory.configureSessionFactory() is used, we use 'HibernateUtils.newSessionFactory("hibernate.test.cfg.xml")`.

I got the exception :

 org.hibernate.HibernateException: Could not instantiate dialect class
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:82)
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:64)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:146)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:71)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2277)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2273)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1742)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1782)
at test.HibernateUtils.newSessionFactory(HibernateUtils.java:27)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassCastException: org.hibernate.dialect.HSQLDialect cannot be cast to org.hibernate.dialect.Dialect
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:73)
... 37 more

java.lang.NullPointerException
at test.HibernateDbUnitTestCase.tearDown(HibernateDbUnitTestCase.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.MethodRoadie.runAfters(MethodRoadie.java:149)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:101)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

You can see the codes below.

Thank you for your reply. If you have another way to access the isolated database, I'd be glad to hear it.


Player.class
public class Player extends TablePlayer {

    private List<Item> items;

    //other attributes…

    /*
     * This method set the list of potions of the player based on the query from the database.
     */

    public void show_Potions() throws Exception {

        SessionFactory sf = HibernateSessionFactory.configureSessionFactory();
        Session session = sf.getCurrentSession();
        session.getTransaction().begin();

        try {

            StringBuilder query = new StringBuilder();
            query.append("from TableItems items " +
                    "left join fetch items.name " +
                    "left join fetch items.type " +
                    "left join fetch items.idPlayer player " +
                    "where player.id = :pid ");
            query.append("order by items.dateObtained desc");

        List<TableItems> tableItems = session.createQuery(query.toString()).setParameter(“pid”, this.getId()).list();

        List<Item> potions = new ArrayList<Items>();

        for(TableItems tItem : tableItems){
            Item item = new Item(tItem);
            if(item.getType()).equals(“POTION”){
                potions.add(item);
            }       
        }

        this.setItems( potions );

        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        } finally {
            session.clear();
            session.close();
        }       
    }

    /*
     *  Constructor
     */


    public Player(String id) { // Create a player based on the ID found in the Database
    }

    // other methods...

}

PlayerTest
@RunWith(PowerMockRunner.class)
@PrepareForTest(HibernateSessionFactory.class)
public class PlayerTest extends HibernateDbUnitTestCase {

    private Player player
    private Player player_to_spy;
    private List<Item> actual_items;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        player_to_spy = new Player(“1”);
        player = spy(player_to_spy);
        actual_items = new ArrayList<Item>();
    }

    protected IDataSet getDataSet() throws Exception {  
           return new FlatXmlDataSet(this.getClass().getResourceAsStream("/test/database.xml"));
        }  


    @Test
    public void testShow_Potions() throws Exception {

        PowerMockito.mockStatic(HibernateSessionFactory.class);
        Mockito.when(HibernateSessionFactory.configureSessionFactory()).thenReturn(sessionFactory);     // sessionFactory is an attribute of HibernateDbUnitTestCase
        Mockito.when(HibernateSessionFactory.configureSessionFactory().getCurrentSession()).thenReturn(session); //session is an attribute of HibernateDbUnitTestCase

        player.setId(“1”);      
        player.show_Potions();
        actual_items = player.getItems(); // return the list of items.

        List<Items> expected_items = new ArrayList<Items>();

        Item item1 = new item(“1”); // create an Item of id n°1 based on the database
        expected_items.add(item1);

        assertThat(actual_items,isEqualTo(expected_items)); // I’ve written the isEqualTo() method.
    }

    @After
    public void destroy() throws Exception {
        player_to_spy = null;
        player = null
        actual_items = null;
    }
}

Answer:

The error message is pretty explicit about what the problem is.

Check your configuration and verify that you've properly configured the dialect and that it is pointing to the proper dialect class name. If it is, make sure that the dialect is actually on the classpath if it is a custom dialect implementation.

Question:

I already have mock EntityManager in the test. But now I need mock EntityManager also in my real class(validator of the custom constraint annotation).

In the test I doing so

@RunWith(MockitoJUnitRunner.class)
public class SomeConstraintValidatorTest {

    @Mock
    private EntityManager entityManager;

In the validator I can not do the same, because can not resolve import org.junit.runner.RunWith in Intellij Idea. For build I'm using Gradle.'gradle deploy' going successfully, but when I start Test I get following errors in Idea console

Error:(6, 25) java: package org.junit.runners does not exist Error:(21, 2) java: cannot find symbol symbol: class RunWith

The reasons on which I need mock EntityManager is error below while testing

org.hibernate.AssertionFailure: null id in com.clients.entity.CClient entry (don't flush the Session after an exception occurs)


Answer:

The @RunWith annotation is made for test classes only. If you want to inject the EntityManager in your validation class, I would recommend using field injection.

I assume your ConstraintValidator has a field with the name 'entityManager'.

@RunWith(MockitoJUnitRunner.class)
public class SomeConstraintValidatorTest  {
    @Mock
    private EntityManager entityManager;
    @InjectMocks
    private ConstraintValidator myValidator;
}

more information can be found here

Question:

I am getting a NullPointer exception and while debugging the code I get an InvocationTargetException. I have no clue where am I going wrong. Can someone please help me fix this!!

 @Inject
 private Log log;

 @PersistenceContext(name = Configuration.PERSISTENT_CONTEXT)
 private EntityManager em;

 public List<Vehicle> getData() {
    List<Vehicle> resultList = new ArrayList<>();

    try {
       String sql = "SELECT v FROM Vehicle v JOIN v.car c WHERE c.carType = 'BMW'";

       //getting an InvocationTargetException here while debugging as junit
       Query query = em.createQuery(sql, Vehicle.class);
       resultList = query.getResultList();

       if(resultList == null){
         log.error("List is empty or null");
         return null;
       }

    } catch (IllegalArgumentException ex) {
         log.info(ex.getMessage());
         log.trace(ex.getCause());
    }

    return resultList;
}

This is my Junit:

@InjectMocks
private FinderManager classUnderTest;

private Query query;

private EntityManager emMock;

@Before
public void setUp(){
    emMock = Mockito.mock(EntityManager.class);
    query = Mockito.mock(Query.class);
    Mockito.mock(Vehicle.class);
}

@Test
public void testMethod(){
    List<Vehicle> resultList = new ArrayList<>();

    Mockito.when(emMock.createQuery(Mockito.any(String.class)).thenReturn(query);
    Mockito.when(query.getResultList()).thenReturn(resultList);

    classUnderTest.getData();
}

Trying to find a solution and fix this since so long!


Answer:

It could be because of the fact that you are mocking createQuery method with only String as parameter while actually in your method you are invoking createQuery method with String as well as class parameter. Mock the method with correct signatures in the test method.

Secondly there is no assertion statement or verify in your test method, what exactly are you going to test?