Mockito Assert resulting NullPointerException - java

I am writing a simple test case but getting a null pointer exception in the return value.
Although when I debug the actual mocking is working , and my main code is also being triggered
My Test Case
#Test
public void testEmptyRequests() {
List<MyPojo> list = new ArrayList();
String env = "env-stub";
when(myService.fetchRecords(env)).thenReturn(list);
Assert.assertEquals(Integer.valueOf(0), myController.process(env, 1));
}
My Method
#Async
public Integer process(String environment, Integer id) {
List<MyPojo> list = myService.fetchRecords(environment);
if (list == null || list .isEmpty()) {
log.info("[0] claims to process");
return 0;
}
// Other logic here, Not relevant to this test case
}

change your test method to this:
#Test
public void testEmptyRequests() {
List<MyPojo> list = new ArrayList();
String env = "env-stub";
when(myService.fetchRecords(Mockito.anyString())).thenReturn(list);
Assert.assertEquals(Integer.valueOf(0), myController.process(env, 1));
}
You should mock the method you are using inside your code.

Related

Mockito -- Response from service returns null in test - Java

I'm working on testing a class. This class calls on a service (let's say its called client, and we want to call client.put())
put() should return a response, but at least in the test, the response is null
I don't know if I just didn't setup the mock correctly and wanted to sanity check with you guys here
public class ATest {
#Mock
private ServiceProto.PutItemsResponse res;
...(private variables)...
#Before
public void setUp() throws Exception {
client = mock(Client.class);
clientFactory = mock(ClientFactory.class);
when(clientFactory.get(any())).thenReturn(client);
...(initializing private vars for constructor as mock variables, example below...)
captionConverter = mock(CaptionToCTItemConverter.class);
when(privateVar.convert(any(obj.class))).thenReturn(Item.newBuilder().build());
classAToTest = spy(new ClassAToTest(private variables);
}
#Test
public void putItem() {
long id = 4710582L;
AObject aObject = testUtils.getObject();
doReturn(res).when(client).putItems(any(ServiceProto.PutItemsRequest.class));
System.out.println("result is "+ res);
try {
classAToTest.putMethod(aObject);
}
catch (NullPointerException e) {
}
verify(creativeToolsClient, Mockito.times(1)).putItems(any(IngestionServiceProto.PutItemsRequest.class));
}
}
And this is the method being tested
public void putMethod(AObject aObject) {
final String id = Long.toString(aObject.getId());
ServiceProto.PutItemsResponse putItemsResponse = null;
Exception putItemsFailure = null;
putItemsResponse =
client.putItems(ServiceProto.PutItemsRequest.newBuilder()
.putItems(
id,
ServiceProto.PutItemsRequest.Item.newBuilder()).build())
.build());
if (putItemsResponse == null) {
logger.warning("PutItems request has failed: "+
(putItemsFailure == null ? "null" : putItemsFailure.getMessage()));
}
}
and when I run it it gives the warning
The putItems method works for other people. Did I set up mock incorrectly?
res variable is not initialized. To mock objects with #Mock annotation use
#ExtendWith(MockitoExtension.class)
public class ATest {
...

Mockito ArgumentCaptor does not return any values on verification

I am trying to use argument capture to determine what arguments are being passed to a mocked Mockito method, but I am not able to capture any values.
class CombinedEvent
{
final List<String> events;
public CombinedEvent() {
this.events = new ArrayList<>();
this.events.add("WATCHITM");
this.events.add("BIDITEM");
}
}
Holder class
class CombinedNotificationAdapter {
private CombinedEvent combinedEvent;
CombinedNotificationAdapter() {
this.combinedEvent = new CombinedEvent();
}
public boolean isEnabled(String user, NotificationPreferenceManager preferenceManager) {
boolean status = true;
for (String event : combinedEvent.events) {
status = status && preferenceManager.isEventEnabled(user, event);
}
return status;
}
}
My unit test
#RunWith(JUnit4.class)
class CombinedNotificationAdapterTest {
private CombinedNotificationAdapter adapter;
#Mock
private NotificationPreferenceManager preferenceManager;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
adapter = new CombinedNotificationAdapter();
}
#Test
public void testIsEnabled() {
doReturn(true).when(preferenceManager).isEventEnabled(eq("test"), anyString());
Assert.assertTrue(adapter.isEnabled("test", preferenceManager));
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(preferenceManager, times(2)).isEventEnabled(eq("test"), captor.capture());
System.out.println(captor.getAllValues());
}
}
The output of captor.getAllValues() is an empty list. I would like the values to return a list of WATCHITM and BIDITEM. I don't know what I am going wrong.
Reference:
https://static.javadoc.io/org.mockito/mockito-core/2.28.2/org/mockito/Mockito.html#15
https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/ArgumentCaptor.html
I think you are overdoing:
doReturn(true)
. when(preferenceManager)
.isEventEnabled(eq("test"), anyString()):
You are scrubbing that expected method invocation and then combining that with your argument captor. And that does not work. You can either stub or capture, not both things! See this existing question for example.
My suggestion: look at this answer and learn how to create your own Answer object. Those get passed an instance of InvocationOnMock. And that class allows you to check the arguments passed into the mocked calls, too!

How can I JUnit test "printlist"?

I have been staring at this code for quite some time now and I really can't figure out how and what to do for its JUnit testing.
static void printList(OrderedIntList list) {
System.out.print("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
System.out.print(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
This code is from a utility class called orderedIntList, which is an array list.
Well... think about the contracts of this method: What does it promise? It promises to print a list of integers, separated by a comma, and inside of brackets. So, you could specify this in a unit test.
Edit2: Just in case you fancy unit testing whether the list is printed in order: I would not consider this a property of the printList method. This property should be tested in the methods that modify the OrderedIntList.
Write a fixture for some Lists with the string that you expect to be printed. Don't forget the corner case: An empty list. Then, maybe a list of size 1 and one of size 10.
To check what has been printed, you can create a new PrintStream, and set the value of System.out, by calling System.setOut. Do this at the beginning of each test, and don't forget to reset System.out (so don't forget to store its original value). The PrintStream you use need not be fancy: You simply must be able to compare the printed stream. You may want to consider using Mockito for that matter.
Edit:
For example, the following code tests whether the list containing the sole element 4, actually prints the string "[4]\n":
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
/* Setup */
final StringBuffer printStream = new StringBuffer();
PrintStream mockedOut = mock(PrintStream.class);
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(anyString());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(anyString());
PrintStream originalOut = System.out;
System.setOut(mockedOut);
/* the actual test */
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
OrderedIntList.printList(list);
MatcherAssert.assertThat(printStream.toString(), is("[4]\n"));
/* Teardown - reset System.out */
System.setOut(originalOut);
}
Note that you probably want to extract the setup- and the teardown part to use it in other tests and to make your test readable. If I am not mistaken, JUnit provides functionality to add code that gets invoked before and after each test execution if you specify it with an #Before and #After annotation.
Obviously, you do not necessarily need Mockito to achieve this. You can also write a class that implements PrintStream and stores the printed strings. In this case, Mockito simply allows you to ignore all the methods you do not care about (i.e., you do not need to implement the whole PrintStream interface)
A small sidenote on the duplication of the stubing: We need to stub both methods, print and println, because both are used. Also, because of overriding, print(String x) is not the same as print(Object x), so we need to stub them both.
#Kulu Limpa answer is correct but much more complicated than the actual implementation, because you need some mocking.
if you refactor your code to
static void printList(OrderedIntList list) {
System.out.println(toString(list));
}
static String toString(OrderedIntList list) {
StringBuilder result = new StringBuilder();
System.out.println(toString(list));
result.append("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
result.append(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
result.append(", ");
}
}
result.append("]");
return result.toString();
}
testing should be much easier:
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
String result = OrderedIntList.toString(list);
MatcherAssert.assertThat(result, is("[4]"));
}
The library System Rules has a JUnit rule called StandardOutputStreamLog. With this rule you are able to test your code, that writes to System.out:
public void MyTest {
#Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
#Test
public void test() {
OrderedIntList list = ...
printList(list);
assertEquals("[1,2,3,4]", log.getLog());
}
}

JUnit test - method called on class instance

I have a problem with JUnit test for my method
#Transactional
#Override
public void deleteOffer(Offer offer) {
List<String> offerPictures = this.getOfferPictures(offer);
if (offerPictures != null) {
System.out.println(offerPictures.size());
for (String stringName : offerPictures) {
this.deleteSinglePhoto(new File(hardDiscAddress + stringName));
this.deleteSinglePhoto(new File(hardDiscAddress + "sm_" + stringName));
}
}
offerDAO.delete(offer.getId());
}
I already have test for empty offerPcitures list, but now I need to write one for NOT empty list. Problem is I don't know how to mock getOfferPictures method to return not empty string list
#Override
public List<String> getOfferPictures(Offer offer) {
File dir = new File(hardDiscAddress);
List<String> resultantlist = new ArrayList<String>();
if (dir.isDirectory()) {
for (final File f : dir.listFiles()) {
if (f.getName().startsWith(offer.getPhotography())) {
resultantlist.add(f.getName());
}
}
}
return resultantlist;
}
And this is the test for empty list
#Test
public void testDeleteOffer() {
// given
testOfferServiceImpl = new OfferServiceImpl();
testOfferServiceImpl.hardDiscAddress = "C:/";
testOfferServiceImpl.offerDAO = offerDAOMock;
when(offerMock.getId()).thenReturn(1);
when(offerMock.getPhotography()).thenReturn("stringForTest");
doNothing().when(offerDAOMock).delete(1);
// when
testOfferServiceImpl.deleteOffer(offerMock);
// then
Mockito.verify(offerDAOMock, times(1)).delete(1);
}
You could use Mockito.spy to partially mock the instance you're testing, and return a non empty list:
#Test
public void testNotEmptyOffer() {
// Given
testOfferServiceImpl = new OfferServiceImpl();
testOfferServiceImpl.hardDiscAddress = "C:/";
testOfferServiceImpl.offerDAO = offerDAOMock;
// Spy (partially mock) the object
testOfferServiceImpl = Mockito.spy(testOfferServiceImpl);
doReturn(Arrays.asList("one", "two", "three")).
when(testOfferServiceImpl).getOfferPictures(offerMock)
// Test your logic here
}
Use something like Mockito. You can do:
Candidate candidate = mock(Candidate.class);
when(candidate.getFirstName()).thenReturn("Bob");
this is an example from project, works well. You will also have to annotate your test class with:
#RunWith(MockitoJUnitRunner.class)
you can then make the method return whatever you like. Hope that helps :)

doAnswer() to modify passed objects is not being called for Void method

Use Case:
I want to call a method of mocked class with list of objects and want to modify passed parameters. It works fine if I work on some method with return type and doesn't work for Void returning methods.
Method to test:
public class TestClass{
#Autowired
PersistActivity activity;
public void methodToTest(List<URLObject> urlObjects) {
List<URLObject> urlObjects2PerformAction = new ArrayList<URLObject>();
for (URLObject urlObject : urlObjects) {
// Added this check to make sure, we are not running a previous
// activity which is successful.
if (urlObject.getRetryCountMap().get(currentActivityName) != null) {
urlObjects2PerformAction.add(urlObject);
}
}
boolean activityStatus = true;
try {
log.info("Calling activity " + currentActivityName + " with " + urlObjects2PerformAction);
activity.doActivity(urlObjects2PerformAction);
log.info("UrlObjects are " + urlObjects2PerformAction);
} catch (Exception e) {
//another set of actions.
}
for (URLObject urlObject : urlObjects) {
if (!urlObject.isActivitySuccessful()) {
// If complete call failed or partial data failed, update
log.info("Failed for message " + urlObject);
} else {
log.info("Passed for message " + urlObject);
}
}//end for
}//end method
}//end class
In this example, I want to modify urlObjects to populate one of its boolean variable to be true/false.
I have added a doAnswer() clause in test case like this:
Test Class:
public class TestMe{
#Mock
private PersistActivity activity;
#Captor
private ArgumentCaptor<List<URLObject>> argument;
#InjectMocks
private DCUrlPersistor dcUrlPersisor = new DCUrlPersistor();
#Test
public void runIndividualDeamonWithMultipleMessagesSomeFailing() throws Exception {
URLObject urlObject1 = getUrlObject(normalizedUrl, normalizedUrl, scraperName);
URLObject urlObject2 = getUrlObject("test2.com", "test2.com", "gpsUS");
Map<String,Integer> retryCountMap = new HashMap<String, Integer>();
retryCountMap.put(PersisterActivitiesEnum.CSI.getName(), 0);
urlObject1.setRetryCountMap(retryCountMap);
urlObject2.setRetryCountMap(retryCountMap);
/**
* Change argument passed to the method.
*/
doAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation)
throws Throwable
{
Object[] arguments = invocation.getArguments();
if ( arguments != null
&&
arguments.length > 0
&&
arguments[0] != null)
{
List<URLObject> objs = (List<URLObject>) arguments[0];
Assert.assertNotNull(objs.get(0).getRetryCountMap());
objs.get(0).setActivitySuccessful(false);
}
return null;
}
}).when(activity).doActivity(anyList());
doNothing().when(activity).doActivity(Arrays.asList(urlObject1, urlObject2));
/**
* Call method.
*/
dcUrlPersisor.methodToTest(Arrays.asList(urlObject1, urlObject2));
/**
* Verify various instances and logs.
*/
verify(activity, times(1)).doActivity(argument.capture());
assertEquals(2, argument.getValue().size());
assertEquals(normalizedUrl, argument.getValue().get(0).getNormalizedURL());
Assert.assertTrue(logContains("Calling activity csi with "));
//-----This is the part which fails as log never prints this message----//
Assert.assertTrue(logContains("Failed for message"));
}
}
Issue:
If I change the return type of doActivity method to be List<ABC> than Void, then it gets called and works as expected (without changing the test code).
Do we need some changes for void methods? I have already set it to return void in doAnswer.
Any help would be appreciated.
Try removing the following line:
doNothing().when(activity).doActivity(Arrays.asList(urlObject1, urlObject2));
To me, it seems a bit contrary to the doAnswer set up that precedes it.
Change Void to Object like this.
...
doAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
...

Categories

Resources