Mocking a private method in junit using Powermockito - java

I need to mock following method call carBookBuilder.setTrip(protoConverter.convertTrip(carBookRequest, location)), But When carBookBuilder.setTrip(protoConverter.convertTrip(carBookRequest, location)) is calling i should just return mocking tripdetails and skip protoConverter.convertTrip(carBookRequest, location) method call.
ProtoRequestAdapterTest.java
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProtoRequestAdapter})
class ProtoRequestAdapterTest {
#Test
public void testPopulateCarBookTest() {
CarApiToProtoConverter carApiToProtoConverter;
carApiToProtoConverter = PowerMockito.mock(CarApiToProtoConverter.class);
PowerMockito.when(carApiToProtoConverter.convertTripDetails(carBookRequest, locale)).thenReturn(tripDetails);
}
}
ProtoRequestAdapter.java
class ProtoRequestAdapter {
private CarBookRequest populateCarBook(BookingRequest bookingRequest) {
CarBookRequest newCarBookReq = bookingRequest.getCarBookRequest();
CarBookRequest.Builder carBookBuilder = CarBookRequest.newBuilder();
ProtoConverter protoConverter =
new ProtoConverter(refData, location);
carBookBuilder.setTrip(protoConverter.convertTrip(carBookRequest, location));
return carBookBuilder;
}
}

I see several problems here.
If I understand you correctly, you are trying to test
ProtoRequestAdapter#populateCarBook.
First of all you should make the method public or at least protected, as otherwise your unit test can not call it.
Next the method you are trying to mock is ProtoConverter#convertTrip, which is not private, as otherwise your code would not compile.
More problematic is that you are instantiating it directly in your code, which makes it impossible to replace it with a mock.
I would strongly suggest you to inject it into your class (or at least move the instantiation into a (protected) getProtoConverter()-method, which you can overwrite in your test).

You have to instantiate tripDetails in your test class.
TripDetails tripDetails = new TripDetails();
tripDetails.setLocation = "London";

Related

Mockito: Mocking different classes method in a specific class scope

I'd like to do this mocking with Mockito
MyServiceClass
(this isn't the actual code, just a fake example with a similar intent)
public String getClassObjects() {
OtherClassObject otherclass = OtherClassObject.createOtherClassObject();
String id = otherclass.getParentObject().getId();
return id;
}
So essentially I want to mock ".getId()" but only in the context of this class "MyServiceClass" if I call the same method of "getId()" in a different class I want to be able to mock a different return.
This will return "3" in every method call for the OtherClassObject
new MockUp<MyServiceClass>() {
#Mock
public String getId(){
return "3";
}
};
Is there a way to isolate method calls for a class object within the scope of a specific class?
Plain Mockito is unable to mock static calls, so you need PowerMock here. To achieve desired you should return different values from the mocked object like this
// from your example it's not clear the returned type from getParentObject method.
// I'll call it ParentObj during this example. Replace with actual type.
ParentObj poOne = mock(ParentObj.class);
when(poOne.getId()).thenReturn("3");
ParentObj poTwo = mock(ParentObj.class);
when(poTwo.getId()).thenReturn("10");
...
OtherClassObject otherClassObjectMock = mock(OtherClassObject.class);
// return all your stubbed instances in order
when(otherClassObjectMock.getParentObject()).thenReturn(poOne, poTwo);
PowerMockito.mockStatic(OtherClassObject.class);
when(OtherClassObject.createOtherClassObject()).thenReturn(otherClassObjectMock);
Thus, you can customize your mocks per needs, specifying desired return value, or propagating call to actual (real) method.
Don't forget to use annotations #RunWith(PowerMockRunner.class) and #PrepareForTest(OtherClassObject.class) on class level to activate the magic of PowerMock.
An alternative idea is to get rid of static call inside your getClassObjects method and pass factory using constructor, so you can easily mock it, setting mocked object only for single class.
Hope it helps!

Mockito - internal method call

I have a class called Availability.java and have two methods.
public Long getStockLevelStage() {
//some logic
getStockLevelLimit();
}
public Long getStockLevelLimit() {
String primaryOnlineArea = classificationFeatureHelper.getFirstFeatureName(productModel, FEATURE_CODE_PRODUCT_ONLINE_AREA_PRIMARY, language);
................
return new Long();
}
I'm writing a unit test class AvailabilityTest.java.
#RunWith(MockitoJUnitRunner.class)
public class AvailabilityTest {
#InjectMocks
private Availability availability = new Availability();
#Test
public void testGetStockLevelStage() {
availability.getStockLevelStage();
}
}
When I call availability.getStockLevelStage() method, it calls getStockLevelLimit() method. Is it possible to mock the internal method call?
In this case, I don't want getStockLevelLimit() to be executed, when getStockLevelStage() gets executes.
Please help.
Try this:
#RunWith(MockitoJUnitRunner.class)
public class AvailabilityTest {
#InjectMocks
#Spy
private Availability availability = new Availability();
#Test
public void testGetStockLevelStage() {
Mockito.doReturn(expectedLong).when(availability).getStockLevelLimit();
availability.getStockLevelStage();
}
}
Here is an article I wrote on Mockito Spying if you need a further read.
if getStockLevelLimit() has not to be executed during your test, it means in a some way you want to mock the class under test.
Doing it reduces the relevance and the authenticity of the behavior tested.
You should mock dependencies and not internal methods of the tested class.
I suppose you don't want to execute getStockLevelLimit() because it uses external dependency that you want to isolate or something of similar.
So you should mock and isolate which is behind getStockLevelLimit() and that doesn't make directly part of the Availability class.

Mockito NotaMockException

I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.
class Activity{
public void firstMethod(){
String str = secondMethod();
}
public String secondMethod(){
String str = null;
/* some Code */
return str;
}
}
Getting exception :
*org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!*
in the below code
class ActivityTest(){
Activity act;
#Before
public void setup(){
act = new Activity();
}
#Test
public void testFirstMethod(){
Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?
I found this post:
Mockito Spy'ing on the object being unit tested
However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.
I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.
As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.
Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.
class ActivityTest() {
Activity act;
#Before
public void setup(){
act = Mockito.spy(new Activity()); // Here!
}
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:
#RunWith(MockitoJUnitRunner.class)
class ActivityTest() {
#Spy
Activity act = new Activity();
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.
public class ActivityTest() {
private Activity act = new Activity();
#Test
public void testSecondMethod(){
assertEquals("expected-value", act.secondMethod());
}
#Test
public void testFirstMethod() {
act.firstMethod();
// success if no exception occurs
}
}
Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.
I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...
Here are some hints:
Mock the Activity.
Tweak the behavior of secondMethod with when / then / doReturn
Use doCallRealMethod when firstMethod is invoked.
Hope it helps.

Mocking helper class with Mockito

I have a plain helper class with public methods which I am using in the service level class. When I am writing test for the service class and trying to mock this helper class for one of the method it is going inside the methods and running every line. Since code inside this method is more complex I want to mock helper class with method(s) so that I don't have to take care of every detail inside helper class method.
Service Class
class HistoryServiceImpl implements CaseHistory {
#Override
public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
MemberUtil memberUtil = new MemberUtil();
List<CaseHistoryDto> caseHistoryDtoList = new ArrayList<CaseHistoryDto>();
List<CaseHistory> caseHistoryList = caseDetailDao.fetchCaseHistory(member.getId(), provider.getId());
for(CaseHistory caseHistory : caseHistoryList) {
CaseHistoryDto caseHistoryDto = new CaseHistoryDto();
caseHistoryDto.setMemberInfo(memberUtil.getMemberInfo(member, caseHistory.getCreateDate()));
caseHistoryDtoList.add(caseHistoryDto);
}
return caseHistoryDtoList;
}
}
Test Class
Class HistoryServiceTest {
#Mock MemberUtil memberUtil;
#InjectMocks private HistoryServiceImpl historyServiceImpl = new HistoryServiceImpl();
#Test
public void testGetCaseHistory() {
//why this line going inside real method and executing all lines?
when(memberUtil.getMemberInfo(any(Individual.class), any(Date.class))).thenReturn(member);
}
}
The reason that your test case is running all the lines in the "real" method, is because your mock object is never being used anywhere.
As written, you cannot mock MemberUtil in your HistoryServiceImpl, because you are manually instantiating it in the getCaseHistory() method. You need to make getCaseHistory() get its MemberUtil from somewhere else, so that you can inject your mock version in your test class.
The simplest solution would be to define your MemberUtil as a member variable, so that the #InjectMocks annotation can override the default value:
class HistoryServiceImpl implements CaseHistory {
MemberUtil memberUtil = new MemberUtil();
#Override
public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
...
}
}
Alternately you could have HistoryServiceImpl accept an externally provided MemberUtil, either in its constructor or via a setter method. You can then easily pass in a mocked version in your test class.
Generally, utility classes are stateless, so another possible solution would be to convert MemberUtil to make all of its methods static. Then you can use something like PowerMock to mock your static methods.

Unit Testing Java Code - Mocking a non-static method of a different class

public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}

Categories

Resources