Questions on 1-day #JUnit, #Mockito, #TDD, #Refactoring

19 views
Skip to first unread message

VikramSrinivasan Venkatakrishnan

unread,
Feb 13, 2017, 6:58:55 PM2/13/17
to Sang Shin, jpassi...@googlegroups.com
Please assist with my below question. 

Let's say we are refactoring the Person class. 

Before Person class:

Person.java has a method , 

public String getPersonAddressInfo(){
Address address = new Address ();
return address.getInfo();

}

After refactor Person class:

@Autowired
Address address;

public String getPersonAddressInfo(){
return address.getInfo();

}

Now , if we write a junit as below, mocking the address object,

@Mock
Address address;

@Inject Mock
Person person;


@setup{ required code}

@Test public void
should_return_adress_info_as_something(){
    Mockito.when(address.getInfo()),thenReturn("Westbrough,MA");
    assertThat(person.getPersonAddressInfo, equalTo("Westborough,MA"));
}

The method should_return_adress_info_as_something works only for the After class and not Before class. Why is this the case ? Is it because we are creating a new object in the Before Person Class ? 

Now, in the After class example that was given, let's say my prod app is not on spring framework , how would i get an instance of my address object ?

Kindly assist. 

Thanks,
Vikram

VikramSrinivasan Venkatakrishnan

unread,
Feb 13, 2017, 7:16:44 PM2/13/17
to Sang Shin, jpassi...@googlegroups.com
I can see in the dependency injection video , you say the object cannot be mocked since it's created with that class as it beats the point of unit testing.

Now lets say,

Person class is changed to support dependency injection (no spring framework)

Person.java

public class Person(){

Address address
   public void Person (Address address){
       this.address = address;
}

public String getPersonAddressInfo(){
return address.getInfo();

}

}

I am assuming this should work, meaning we should be able to Mock the Address obejct ? But lets say the Person object is created in a Request Handler class. While testing RequestHandler we wont be able to mock the objects right ? I hope you got my question. How do we handle this ?


RequestHandler.java

public void process (Person person){
Address address = new Address;
person = new Person (address);
person.getPersonAddressInfo();
}


Thanks,
Vikram

Sang Shin

unread,
Feb 14, 2017, 12:09:52 PM2/14/17
to VikramSrinivasan Venkatakrishnan, jpassi...@googlegroups.com, jpassion_ad...@googlegroups.com


On 2/13/2017 7:16 PM, VikramSrinivasan Venkatakrishnan wrote:
I can see in the dependency injection video , you say the object cannot be mocked since it's created with that class as it

I assume you meant it's created "within" that class..


beats the point of unit testing.


Correct.


Now lets say,

Person class is changed to support dependency injection (no spring framework)

Dependency injection can happen in many different ways indeed

-via constructor
-via setter method
-via passing the dependency as a method argument
-Spring @Autowired
-CDI @Inject



Person.java

public class Person(){

   Address address
   public void Person (Address address){
       this.address = address;
}

Yes, this is via constructor method



public String getPersonAddressInfo(){
return address.getInfo();

}

}

I am assuming this should work, meaning we should be able to Mock the Address obejct ?

Correct.

But lets say the Person object is created in a Request Handler class. While testing RequestHandler we wont be able to mock the objects right ? I hope you got my question. How do we handle this ?

You do mocking only during testing.  The code below is in non-testing (production)
environment and has nothing to do with testing.  (In fact, even if you do not
have any dependency injection scheme mentioned above, you can still inject
dependency to the target class.)  I will demonstrate this during our March 1st
codecamp if you want.

-S
-- 
-------------------------------------------------------------------
             Sang Shin, sangshi...@gmail.com
         http://www.linkedin.com/in/javapassion (Linkedin)
          http://twitter.com/javapassion (Tweeter)
            Life is worth living... with Passion!
----------------------------------------------------------------------

Sang Shin

unread,
Feb 14, 2017, 12:25:59 PM2/14/17
to VikramSrinivasan Venkatakrishnan, jpassi...@googlegroups.com, jpassion_ad...@googlegroups.com

I made a bit confusing statement at the end.  I clarified a bit.


But lets say the Person object is created in a Request Handler class. While testing RequestHandler we wont be able to mock the objects right ? I hope you got my question. How do we handle this ?

You do mocking only during testing.  The code below is in non-testing (production)
environment and has nothing to do with testing.  (In fact, even if you do not
have any dependency injection scheme mentioned above, you can still inject
dependency to the target class.) 

I meant to say "(In fact, even if you do not

have any dependency injection scheme mentioned above, you can still inject
dependency to the target class via mocking.)"  In other words, even if you
do not have the constructor method in which Address object is passed
as a constructor argument, you can still inject Address object to the
Person object via @InjectMocks.  Of course, if you do this, the production
code will not work. :-) 

-Sang

VikramSrinivasan Venkatakrishnan

unread,
Feb 14, 2017, 4:11:52 PM2/14/17
to Sang Shin, jpassi...@googlegroups.com, jpassion_ad...@googlegroups.com
I have got the part with how the Mocking works, it's just that I am trying to understand how to refactor a code by using Dependency injection . My question is , even if there is dependency injection in a class A where the injected object O is passed to it's constructor , The object O should be created in some X class so it can be injected to A's constructor or set in a setter method. Now does that mean we can't unit test that X class mocking this O object because we are creating a new instance of O there ?  


Thanks,
Vikram

Sang Shin

unread,
Feb 15, 2017, 8:02:29 AM2/15/17
to VikramSrinivasan Venkatakrishnan, jpassi...@googlegroups.com, jpassion_ad...@googlegroups.com


On 2/14/2017 4:11 PM, VikramSrinivasan Venkatakrishnan wrote:
I have got the part with how the Mocking works, it's just that I am trying to understand how to refactor a code by using Dependency injection . My question is , even if there is dependency injection in a class A where the injected object O is passed to it's constructor , The object O should be created in some X class so it can be injected to A's constructor or set in a setter method. Now does that mean we can't unit test that X class mocking this O object because we are creating a new instance of O there ? 

Good question.   If the X does not use object O in its logic, in other words, it does not
call the method of the O, there is no need to mock the behavior of O, hence injecting
O or creating O does not have any consequence to the unit testing of X.

-S

VikramSrinivasan Venkatakrishnan

unread,
Feb 15, 2017, 9:57:42 AM2/15/17
to Sang Shin, jpassi...@googlegroups.com, jpassion_ad...@googlegroups.com
Wow ! I got it ! I can see the light at the end of the tunnel now :)
That makes sense, we will have a setter method in the X class which will inject this object by creating a new instance . 
Also, as per jnuit we don't have to test setter method so we can skip the code coverage for that setter method in X. Thanks for clarifying this . 

Thanks,
Vikram
Reply all
Reply to author
Forward
0 new messages