Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a mocked object to a class which do not have a setter or a constructor for that variable?

Tags:

java

mockito

Person.java

public class Person
{
    private final Integer personID;
    private final String personName;
    public Person( Integer personID, String personName )
    {
        this.personID = personID;
        this.personName = personName;
    }
    public Integer getPersonID()
    {
        return personID;
    }
    public String getPersonName()
    {
        return personName;
    }
} 

PersonDAO.java

public interface PersonDao
{
    public Person fetchPerson( Integer personID );
    public void update( Person person );
} 

**PersonService.java** 

public class PersonService
{
    private final PersonDao personDao;
    public PersonService( PersonDao personDao )
    {
        this.personDao = personDao;
    }
    public boolean update( Integer personId, String name )
    {
        Person person = personDao.fetchPerson( personId );
        if( person != null )
        {
            Person updatedPerson = new Person( person.getPersonID(), name );
            personDao.update( updatedPerson );
            return true;
        }
        else
        {
            return false;
        }
    }
} 

PersionServiceTest.java

public class PersonServiceTest
{
    @Mock
    private PersonDao personDAO;
    private PersonService personService;
    @Before
    public void setUp()
        throws Exception
    {
        MockitoAnnotations.initMocks( this );
        personService = new PersonService( personDAO );
    }
    @Test
    public void shouldUpdatePersonName()
    {
        Person person = new Person( 1, "Phillip" );
        when( personDAO.fetchPerson( 1 ) ).thenReturn( person );
        boolean updated = personService.update( 1, "David" );
        assertTrue( updated );
        verify( personDAO ).fetchPerson( 1 );
        ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass( Person.class );
        verify( personDAO ).update( personCaptor.capture() );
        Person updatedPerson = personCaptor.getValue();
        assertEquals( "David", updatedPerson.getPersonName() );
        // asserts that during the test, there are no other calls to the mock object.
        verifyNoMoreInteractions( personDAO );
    }
    @Test
    public void shouldNotUpdateIfPersonNotFound()
    {
        when( personDAO.fetchPerson( 1 ) ).thenReturn( null );
        boolean updated = personService.update( 1, "David" );
        assertFalse( updated );
        verify( personDAO ).fetchPerson( 1 );
        verifyZeroInteractions( personDAO );
        verifyNoMoreInteractions( personDAO );
    }
} 

/* In the above example mocked personDAO object is sent to the personService class object through the constructor of the personService(in personServiceTest class).

My doubt is how to pass the mocked personDAO object to the personService class if it is not having any setter or a constructor?

i.e what if the personDAO is created using "new" instead of getting from the constructor or setter in the personService class like mentioned in the below code .*/

public class PersonService
{
    private final PersonDao personDao=new PersonDao();

    public boolean update( Integer personId, String name )
    {
        Person person = personDao.fetchPerson( personId );
        if( person != null )
        {
            Person updatedPerson = new Person( person.getPersonID(), name );
            personDao.update( updatedPerson );
            return true;
        }
        else
        {
            return false;
        }
    }
} 

How about using reflectiontestutils.setfield();

like image 899
Saisurya Kattamuri Avatar asked Dec 07 '25 10:12

Saisurya Kattamuri


1 Answers

Using Mockito, you can do that by using @Mock and @InjectMocks and the MockitoJUnitRunner.

This question describes this: Using @Mock and @InjectMocks

like image 155
Benjamin Avatar answered Dec 09 '25 23:12

Benjamin