Calling method on real object instead calling on Mock object - java

I faced next issue when I have been writing Junit tests with using Mockito. My test invokes methods on real object instead mock object and I receive NullPointerException. Here is my code:
public class JSFUtilsTest {
public JSFUtilsTest() { }
JSFUtils jsfUtils = mock(JSFUtils.class);
FacesContext facesContext = ContextMocker.mockFacesContext();
ExternalContext extContext = mock(ExternalContext.class);
Application app = mock(Application.class);
ExpressionFactory exFactory = mock(ExpressionFactory.class);
ELContext elContext = mock(ELContext.class);
ValueExpression valExp = mock(ValueExpression.class);
#Test
public void testResolveExpression() {
when(jsfUtils.resolveExpression("expression")).thenAnswer(new Answer<Object>(){
public Object answer(InvocationOnMock invocation){
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
return valExp.getValue(elContext);
}
});
jsfUtils.resolveExpression(anyString());
verify(jsfUtils).resolveExpression(anyString());
assertNotNull(jsfUtils.resolveExpression(anyString()));
}
}
Instead calling resolveExpression() on Mock, I have got calling on JSFUtils object. JSFUtils.java and JSFUtilsTest.java are located in different packages. Can anybody help me? Thanks in advance!

I assume that this is just an example and in real test you do not call methods on the mock directly, but inject the dependencies to OUT.
You are expecting your mock to answer when you are calling jsfUtils.resolveExpression("expression"). In fact you are not calling it. I would suggest to change it to jsfUtils.resolveExpression(anyString()) and if you need it to be called with some specific string, you can check it the verify block: verify(jsfUtils).resolveExpression("expression");
Also calling jsfUtils.resolveExpression(anyString()); is not the right approach. Method anyString() is designed for stubbing not for real call.

Instead calling resolveExpression() on Mock, I have got calling on JSFUtils object.
Then do not create a mock, but a spy:
//JSFUtils jsfUtils = mock(JSFUtils.class);
JSFUtils jsfUtils = spy(new JSFUtils(/* mocks of dependencies if needed */));
But this is only needed if want to mock the return value of some other method in your class under test to force isolation of your unit.
This is not the case in your example as far as I see. So just write:
//JSFUtils jsfUtils = mock(JSFUtils.class);
JSFUtils jsfUtils = new JSFUtils(/* mocks of dependencies if needed */);
#Test
public void testResolveExpression() {
when(jsfUtils.resolveExpression("expression")).thenAnswer(new Answer<Object>(){
public Object answer(InvocationOnMock invocation){
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
return valExp.getValue(elContext);
}
});
jsfUtils.resolveExpression(anyString());
verify(jsfUtils).resolveExpression(anyString());
assertNotNull(jsfUtils.resolveExpression(anyString()));
This does not make any sense:
You mock the method of your class under test (cut) and then call that very same method. This way you do not verify the behavior of your cut but the behavior of the mocking framework.
Also you call the method twice within the same test method. You should avoid that.
You should change your test to this:
#Test
public void testResolveExpression() {
// arrange (test case specific setup of mocks and DTOs)
when(facesContext.getApplication()).thenReturn(app);
when(app.getExpressionFactory()).thenReturn(exFactory);
when(facesContext.getELContext()).thenReturn(elContext);
when(exFactory.createValueExpression(elContext, "expression", Object.class)).thenReturn(valExp);
when(valExp.getValue(elContext)).thenReturn(anyObject());
// act (call real method on real object)
Object result = jsfUtils.resolveExpression("a valid input");
// assert
assertNotNull(result );
}

Related

How to mock new() call in Mockito?

Its my early days with Mockito so need help. Because of the new() operator, a new object is getting created and the Mock is losing significance. Goal is to prevent execution of the stockValidator.validateRequest() method. Kindly note source code can't be modified.
Sample code shared below,
Is there a way to mock the new() object?
StockResponse buyStock(StockRequest stockRequest) method{
.......
StockValidator stockValidator = new StockValidator(.....);
StockError error = stockValidator.validateRequest(StockRequest stockRequest);
}
StockError validateRequest(StockRequest stockRequest){
......
......
}
#MockBean
StockValidator stockValidator;
#Autowire
StockService stockService;
............
............
when(cardValidator.validateRequest(any(), any())).thenReturn(null);
StockResponse response = stockService.buyStock(stockRequest);
Yes, there is a way to do what you will. Firstly, you do not need to use a spy. A spy is not a mock object. It is an instance on which you can call methods as you would normally, but with additional features.
so do not initialise stockValidator like that, but as:
stockValidator = mock(StockValidator.class);
Or since you are already using #MockBean, you do not have to initialise manually at all.
Mock object will NOT call the actual method, instead just make it return the value you tell it to return.
Now you can allow the validateRequest() method return anything. Possibly
when(stockValidator.validateRequest(any(), any())).thenReturn(true);
Do not forget to initialise the service instance with the same validator object.
edit after change in question:
public class TestClass() {
StockValidator stockValidator = mock(StockValidator.class);
StockService stockService = new StockService(stockValidator);
public void test() {
when(stockValidator.validateRequest(any(),
any())).thenReturn(true);
stockService.buyStock();
}
}

Spring boot mocked object returning null on call

I am using #RunWith(SpringRunner.class) to writing unit test case to mock the object. I am trying to mock the repository instance which is accepting request object and returning response, but in unit test case implementation I have mocked the repository using #MockBean annotation and register the it's method call using Mockito.when(respository.post(request)).thenReturn(response). But this call is returning null.
I faced similar situation, the problem is given parameter in Mockito.when() block may not be the same as spring generated. I'll explain my case below, hope to help you:
Product product = new Product(..);
Mockito.when(service.addProduct(product)).thenReturn(saveProduct)
When I send a request, spring generates new Project object which has same fields with product but instance is different. That is, Mockito cannot catch when statement. I changed it like below and it's worked:
Mockito.when(service.addProduct(Mockito.any())).thenReturn(savedProduct)
I figured it out. But the solution is still weird to me...
I was facing this issue because, I was instantiating the request and response in #Before annotated method... as describing below.
#Before
public void setup() {
Request reqA = new Request();
reqA.set..(..);
Response res = new Response();
res.set..(..);
Mockito.when(this.respository.post(reqA)).thenReturn(res);
}
#Test
public void test() {
// Creating Request instance again with all same properties.
// Such that this req instance is technically similarly as instantiated in #Before annotated method (above).
// By, implementing the equals and hashCode method.
Request reqB = new Request();
reqB.set..(..);
// Getting res as 'null' here....
Response res = this.service.post(reqB);
}
Since, reqA and reqB are technically similar then why mocked call not returning the same response as registered.
If I moved setup() method code inside test() method every thing starts working !!!!!
I had the same issue here, vsk.rahul's comment helped me a lot.
I was trying to to use a method to return a mock interaction, but not succeeded, turning it into a static method gave me the expected behavior.
Problem:
The method bar.foo() was returning null for any interaction
public void test1() {
doReturn(mockReturn()).when(bar).foo();
}
private String mockReturn() {
return "abc";
}
Solution:
The method bar.foo() is returning abc String for any interaction
public void test1() {
doReturn(mockReturn()).when(bar).foo();
}
private static String mockReturn() {
return "abc";
}

use doNothing() for method with return type in mockito

public void attestResults(List<OMInvestigationResultMutableDTO.Id> resultIds, OMRequestSpeciality speciality)
{
List<Answer.Id> attestIds = new ArrayList<Answer.Id>();
for (OMInvestigationResultMutableDTO.Id id : resultIds)
{
Answer.Id answerId = answerIdFactory.createId(id.getValue(), null);
attestIds.add(answerId);
}
orderManagementServiceProvider.getOrderManagementService()
.attestResults(attestIds,
RequestSpeciality.valueOf(speciality.toString()));
}
My problem is how to write unit testing for attestResults()..
I want to try mock orderManagementServiceProvider.getOrderManagementService().attestResults() using doNothing() in mockito.
This is the method orderManagementServiceProvider.getOrderManagementService().attestResults,
public List<Id> attestResults(List<Id> answerIds, RequestSpeciality speciality) {
this.accessHandler.checkAccess(AccessRights.ATTEST_RESULTS);
ArgumentValidator.argument(answerIds, "AnswerIds").notNull().notEmpty();
ArgumentValidator.argument(speciality, "Speciality").notNull();
ResultCreator resultCreator = new ResultCreator(this.resultToolkitAdapter, this.pathologyReportToolkitService);
return resultCreator.attestResults(answerIds, speciality);
}
In this case I have not permission to use powerMockito.
I mocked
when(orderManagementServiceProvider.getOrderManagementService()).thenReturn(omService);
The relevant line in your code under test (cut) is this:
orderManagementServiceProvider.getOrderManagementService()
.attestResults(attestIds,
RequestSpeciality.valueOf(speciality.toString()));
Because of the violation of the Law of Demeter (Don't talk to strangers!) you have to mock both: the instance of the OrderManagementService and of the OrderManagementServiceProvider. Then you have to configure the mock of the later to return the mock of the first when getOrderManagementService() is called.
However, doNothing() only applies to void methods on spys (a wrapped concrete instance of the dependency). void methods on mocks are not called anyway.
If your method has a return value you have to use doReturn() (or doThrow()) so that the cut can act on the methods outcome. By default Mockito will return null, 0or false respectively.
Warning:
The form when(dependency.someMethodWithReturnValue()).thenReturn() does call the mocked method (and throws away its result). This may lead to NPEs if the method accesses member variables or objects returned by other not configured methods in the mock.
PowerMockito is used only if you want to mock static classes. By looking at this,
orderManagementServiceProvider.getOrderManagementService()
.attestResults(attestIds,
RequestSpeciality.valueOf(speciality.toString()));
it doesn't look like static class.
orderManagementServiceProvider = mock(OrderManagementServiceProvider.class);
doNothing().when(orderManagementServiceProvider).getOrderManagementService.attestResults(any(),any());

Unable to execute test method from mocked class

I am writing unit test for methods to find banks near my location.
I mocked the class and tried to call the methods.
But, control is not going to method to execute it.
Below is unit test case.
#Test
public void testFindBanksByGeo() {
String spatialLocation = "45.36134,14.84400";
String Address = "Test Address";
String spatialLocation2 = "18.04706,38.78501";
// 'SearchClass' is class where 'target' method resides
SearchClass searchClass = Mockito.mock(SearchClass.class);
BankEntity bank = Mockito.mock(BankEntity.class);
// 'findAddressFromGeoLocation' and 'getGeo_location' to be mocked. They are called within 'target' method
when(searchClass.findAddressFromGeoLocation(anyString())).thenReturn(Address);
when(bank.getGeo_location()).thenReturn(spatialLocation2);
// 'writeResultInJson' is void method. so needed to 'spy' 'SearchClass'
SearchClass spy = Mockito.spy(SearchClass.class);
Mockito.doNothing().when(spy).writeResultInJson(anyObject(), anyString());
//This is test target method called. **Issue is control is not going into this method**
SearchedBanksEntity searchBanksEntity = searchClass.findNearbyBanksByGeoLocation(spatialLocation, 500);
assertNull(searchBankEntity);
}
What i have tried is also calling the real method on it,
Mockito.when(searchClass.findNearbyBanksByGeoLocation(anyString(), anyDouble())).thenCallRealMethod();
This calls real method but the methods i mocked above, are executing like real one. Means 'mocked methods' are not returning what i asked them to return.
So, what wrong i am doing here ?
why method is not executing?
The method is not getting called because you are calling it on a mock. You should call the method on an actual object.
Or you could use something like this before invoking the method.
Mockito.when(searchClass.findNearbyBanksByGeoLocation(Mockito.eq(spatialLocation), Mockito.eq(500))).thenCallRealMethod();
But I think this is not the way you should write the test. You shouldn't be mocking SearchClass in the first place. Instead there would be a dependency in SearchClass which gets you the address and geo location. You should be mocking that particular dependency.
OK, let's say we have this code:
class Foo {
// has a setter
SomeThing someThing;
int bar(int a) {
return someThing.compute(a + 3);
}
}
We want to test Foo#bar(), but there's a dependency to SomeThing, we can then use a mock:
#RunWith(MockitoJunitRunner.class)
class FooTest {
#Mock // Same as "someThing = Mockito.mock(SomeThing.class)"
private SomeThing someThing,
private final Foo foo;
#Before
public void setup() throws Exception {
foo = new Foo(); // our instance of Foo we will be testing
foo.setSomeThing(someThing); // we "inject" our mocked SomeThing
}
#Test
public void testFoo() throws Exception {
when(someThing.compute(anyInt()).thenReturn(2); // we define some behavior
assertEquals(2, foo.bar(5)); // test assertion
verify(someThing).compute(7); // verify behavior.
}
}
Using a mock we are able to avoid using a real SomeThing.
Some reading:
http://www.vogella.com/tutorials/Mockito/article.html
https://github.com/mockito/mockito/wiki

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