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 {
...
How to test void methods in Mockito with assertSame or assertEquals. I am able to do verify only.
i am getting sonar or PMD rules violation -"JUnit tests should include assert() or fail()".
Below is my sample class with test class.
#Service
public class MyServiceImpl implements IService {
#Autowired
private IDyDBDAO dyDBDAO;
#Override
public void update() {
dyDBDAO.save(getDetailData());
}
#Override
public List<Detail> getCurrentDetail() {
return getDetails(dyDBDAO.findAll());
}
private List<Detail> getDetails(Iterable<Detail> details) {
...blah...
}
private String getPlace(){
Places p = Places.getPlace();//static
return p == null? PlacesUtil.getName("DH"): p.getName;
}
private Detail getDetailData() {
Detail d = new Detail();
d.setName("blah");
d.setDesc("fsdfsdfdsf");
d.setPlace(getPlace());
return d;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({Places.class, PlacesUtil.class})
public class MyServiceImplTest {
#InjectMocks
private MyServiceImpl myServiceImpl;
#Mock
private IDyDBDAO dyDBDAO;
#Test
public void testGetCurrentDetail() {
given(dyDBDAO.findAll()).willReturn(getMockDetails());
assertSame(myServiceImpl.getCurrentDetail().size(), 2);
}
#Test
public void testUpdate() {
PowerMockito.mockStatic(Places.class);
// first update , second update -us-west-2 will update
given(Places.getPlace()).willReturn(PlacesUtil.getName("UH"))
.willReturn(null);
myServiceImpl.syncStatus();
// update again with DH
myServiceImpl.syncStatus();
verify(dyDBDAO, times(2)).save(any(Detail.class));
// how to assert checking here
}
private Iterable<Detail> getMockDetails() {
Detail d1 = new Detail();
d1.setName("blah");
d1.setDesc("fsdfsdfdsf");
d1.setPlace("sdfsdf");
Detail d2 = new Detail();
d2.setName("blahblah1");
d2.setDesc("e345345");
d2.setPlace("8907j");
List<Detail> listOfDetail = new ArrayList<>();
listOfDetail.add(eps1);
listOfDetail.add(eps2);
return listOfDetail;
}
}
You need to capture the value passed to the dao save method. Use mockito's ArgumentCaptor for that. Then assert on that value.
Something along these lines:
ArgumentCaptor<Detail> captor = ArgumentCaptor.forClass(Detail.class);
verify(dyDBDAO, times(2)).save(captor.capture());
Detail detail1 = captor.getValues().get(0)
assertEquals(expectedDetail, detail1)
I would assume that your void method that needs to be tested is update in MyServiceImpl.
Firstly, you can verify if dyDBDAO.save() is called.
Mockito.verify(dyDBDAO).save(Mockito.anyList...);
Secondly, you can check the modified or created records in the database by retrieving them and comparing to the inputs from getMockDetails.
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!
I'm pretty new in unit testing and dont know how to test the following circunstances over a callback for this example class:
public class Foo {
private final ItemLoader loader;
private Bar bar;
public Foo(ItemLoader loader,Bar bar) {
super();
this.loader = loader;
this.bar=bar;
}
public void getItems(ItemStore.Callback callback) {
List<ItemData> itemData = bar.getItemData();
List<Item> items = this.loader.transform(itemData);
callback.onItemsLoaded(items);
}
}
That callback.onItemsLoaded is called with the result of loader.transform
My current test is:
public class ExampleTest extends BaseTestCase {
private Foo foo;
#Mock
private Bar mockBar;
#Mock
private ItemLoader mockItemLoader;
#Mock
private ItemStore.Callback itemLoadCallback;
public void setUp() {
MockitoAnnotations.initMocks(this);
foo = new Foo(mockItemLoader, mockBar);
}
public void testGetItems() {
List<ItemData> mockItemData = (List<ItemData>) mock(List.class);
when(mockBar.getItemData()).thenReturn(mockItemData);
foo.getItems(itemLoadCallback);
verify(mockItemLoader).transform(mockItemData);
}
}
It tests:
That loader.transform is called
That callback.onItemsLoaded is called
But I realised that if I change the last line of the Foo.getItems method like (Notice the null):
public void getItems(ItemStore.Callback callback) {
...
callback.onItemsLoaded(null);
}
The test keep pasing. So I'd need to test that callback.onItemsLoaded is called with the result of loader.transform
So I modified the test:
public void testGetItems() {
List<ItemData> mockItemData = (List<ItemData>) mock(List.class);
when(mockBar.getItemData()).thenReturn(mockItemData);
foo.getItems(itemLoadCallback);
verify(mockItemLoader).transform(mockItemData);
List<Item> resultItems = verify(mockItemLoader).transform(mockItemData);
verify(itemLoadCallback).onItemsLoaded(resultItems);
}
But it complains in the last line saying Argument(s) are different!
How can I fix the test
Because mockItemLoader is a mock, it will actually return an empty list from transform. If you want to make it return something different, you could set up an object for it to return. Basically, this will be your own List<Item>. So you can then stub the tranform method instead of verifying it; and use the same List<Item> when you verify the call to onItemsLoaded.
I have a Java class named, MyClass, that I want to test with JUnit. The public method, methodA, that I want to test calls a private method, methodB, in the same class to determine which conditional path to follow. My goal is to write JUnit tests for the different paths in methodA. Also, methodB calls a service, so I do not want it to actually be executed when I run the JUnit tests.
What is the best way to mock methodB and control its return so that I can test different paths for 'methodA'?
I prefer to use JMockit when writing mocks, so I am specifically interested in any answer that applies to JMockit.
Here is my example class:
public class MyClass {
public String methodA(CustomObject object1, CustomObject object2) {
if(methodB(object1, object2)) {
// Do something.
return "Result";
}
// Do something different.
return "Different Result";
}
private boolean methodB(CustomObject custObject1, CustomObject custObject2) {
/* For the sake of this example, assume the CustomObject.getSomething()
* method makes a service call and therefore is placed in this separate
* method so that later an integration test can be written.
*/
Something thing1 = cobject1.getSomething();
Something thing2 = cobject2.getSomething();
if(thing1 == thing2) {
return true;
}
return false;
}
}
This is what I have so far:
public class MyClassTest {
MyClass myClass = new MyClass();
#Test
public void test_MyClass_methodA_enters_if_condition() {
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
// How do I mock out methodB here to return true?
assertEquals(myClass.methodA(object1, object2), "Result");
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
// How do I mock out methodB here to return false?
assertEquals(myClass.methodA(object1, object2), "Different Result");
}
}
Thanks!
To give the answer you asked for (using JMockit's partial mocking):
public class MyClassTest
{
#Tested MyClass myClass;
#Test
public void test_MyClass_methodA_enters_if_condition() {
final CustomObject object1 = new CustomObject("input1");
final CustomObject object2 = new CustomObject("input2");
new NonStrictExpectations(myClass) {{
invoke(myClass, "methodB", object1, object2); result = true;
}};
assertEquals("Result", myClass.methodA(object1, object2));
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
final CustomObject object1 = new CustomObject("input1");
final CustomObject object2 = new CustomObject("input2");
new NonStrictExpectations(myClass) {{
invoke(myClass, "methodB", object1, object2); result = false;
}};
assertEquals("Different Result", myClass.methodA(object1, object2));
}
}
However, I would not recommend doing it like that. In general, private methods should not be mocked. Instead, mock the actual external dependency of your unit under test (the CustomObject in this case):
public class MyTestClass
{
#Tested MyClass myClass;
#Mocked CustomObject object1;
#Mocked CustomObject object2;
#Test
public void test_MyClass_methodA_enters_if_condition() {
new NonStrictExpectations() {{
Something thing = new Something();
object1.getSomething(); result = thing;
object2.getSomething(); result = thing;
}};
assertEquals("Result", myClass.methodA(object1, object2));
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
new NonStrictExpectations() {{
object1.getSomething(); result = new Something();
object2.getSomething(); result = new Something();
}};
assertEquals("Different Result", myClass.methodA(object1, object2));
}
}
Do not be tempted to mock private methods, even if you can engaging in trickery to do so using a mocking tool. Private members are implementation details, which you should be free to change. Instead use the non-private API to exercise the class. If this is troublesome, consider moving the troublesome code into a different class, if it is not there already, and use dependency injection to inject a mock implementation of the troublesome code.
Make methodB a member of a separate class, and have a private reference to that class within MyClass.
public class MyClass {
private MyOtherClass otherObject = new MyOtherClass();
public String methodA(CustomObject object1, CustomObject object2) {
if(otherObject.methodB(object1, object2)) {
// Do something.
return "Result";
}
// Do something different.
return "Different Result";
}
}
class MyOtherClass {
public boolean methodB(CustomObject custObject1, CustomObject custObject2) {
// Yada yada code
}
}
Personally, I usually only test public methods and look at coverage reports to ensure that all paths have been visited in my private methods. If I really need to test a private method, that's a smell that requires a refactoring as I have above.
You could also use reflection, but I'd feel dirty doing that. If you REALLY want the solution to that let me know and I'll add it to this answer.
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyClass.class })
public class MyClassTest {
// Class Under Test
MyClass cut;
#Before
public void setUp() {
// Create a new instance of the service under test (SUT).
cut = new MyClass();
// Common Setup
// TODO
}
#Test
public void testMethodA() throws Exception {
/* Initialization */
CustomObject object2 = PowerMock.createNiceMock(CustomObject.class);
CustomObject object1 = PowerMock.createNiceMock(CustomObject.class);
MyClass partialMockCUT = PowerMock.createPartialMock(MyClass.class,
"methodB");
long response = 1;
/* Mock Setup */
PowerMock
.expectPrivate(partialMockCUT, "methodB",
EasyMock.isA(CustomObject.class),
EasyMock.isA(CustomObject.class)).andReturn(true)
.anyTimes();
/* Mock Setup */
/* Activate the Mocks */
PowerMock.replayAll();
/* Test Method */
String result = partialMockCUT.methodA(object1, object2);
/* Asserts */
Assert.assertNotNull(result);
PowerMock.verifyAll();
}
}
To mock the private method, you need powermock
The sample code will be like this, but I haven't run it.
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith (PowerMockRunner.class)
public class MyClassTest {
#Test
public void test_MyClass_methodA_enters_if_condition() {
final MyClass myClass = Mockito.mock (MyClass.class);
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
Mockito.when (myClass.methodB(object1, object2)).thenReturn (true);
Mockito.when (myClass.methodA(object1, object2)).thenCallRealMethod ();
assertEquals(myClass.methodA(object1, object2), "Result");
}
}