org.mockito.exceptions.misusing.MissingMethodInvocationException - java

I am getting following exceptions when I run Junit test.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified.
inside when() you don't call method on mock but on some other object.
the parent of the mocked class is not public. It is a limitation of the mock engine.
Following is my code and the exception was thrown at the second when statement. I don't think that my test code didn't violate what the exception claims. I spent for a while, but couldn't figure out. Could someone help? What I need to test is getPermProducts method. In the getPermProducts method, I want to ignore isTempProduct method. So, when p1 came, I want it returns false, and when p2 came, I want it returns true etc..
#Named(ProductManager.NAME)
public class ProductManager {
#Resource(name = ProductService.NAME)
private ProductService productService;
public List<Product> getPermProducts(Set<Product> products) {
Iterator<Product> it = products.iterator();
List<Product> cProducts = new ArrayList<Product>();
Product p;
while (it.hasNext()) {
p = it.next();
if (!isTempProduct(p)) {
cProducts.add(p);
}
}
return cProducts;
}
public Boolean isTempProduct(Product product) {
if (product instanceof PermProduct) {
return false;
}
Set<ProductItems> pItems = product.getProductItems();
if (pItems.isEmpty()) {
return false;
}
Iterator<ProductItem> itr = pItems.iterator();
while (itr.hasNext()) {
if (itr.next() instanceof TempItem) {
return true;
}
}
return false;
}
public Product getProduct(Integer productId) {
Product p = productService.getProduct(productId);
return p;
}
}
#RunWith(MockitoJUnitRunner.class)
public class ProductManagerTest {
#InjectMocks
private ProductManager mockProductManager;
#Mock
private ProductService mockProductService;//not being used here
private static final Integer PRODUCT_ID_1 = 1;
private static final Integer PRODUCT_ID_2 = 2;
#Test
public void getProduct(){
Product p1 = mock(PermProduct.class);
p1.setProductId(PRODUCT_ID_1);
when(mockProductManager.getProductId()).thenReturn(PRODUCT_ID_1);
when(mockProductManager.isTempProduct(p1)).thenReturn(false);
Product p2 = mock(TempProduct.class);
p2.setProductId(PRODUCT_ID_2);
when(mockProductManager.isTempProduct(p2)).thenReturn(true);
List<Product> products = Mock(List.class);
products.add(p1);
products.add(p2);
Iterator<Product> pIterator = mock(Iterator.class);
when(prodcuts.iterator()).thenReturn(pIterator);
when(pIterator.hasNext()).thenReturn(true, true, false);
when(pIterator.next()).thenReturn(p1, p2);
asserEquals(1, mockProductManager.getPermProducts(products).size());
}
}
SOLUTION: I updated my test based on enterbios's answer. I used partial mocking, but as enterbios suggested, we should avoid it, but sometimes we need it. I found that we can have both non-mocked and partial mocked class same time.
#RunWith(MockitoJUnitRunner.class)
public class ProductManagerTest {
#InjectMocks
private ProductManager productManager;//not being used here
#Mock
private ProductService mockProductService;//not being used here
#Spy
private OtherService other = new OtherService();//not being used here
#InjectMocks
final ProductManager partiallyMockedProductManager = spy(new ProductManager());
private static final Integer PRODUCT_ID_1 = 1;
private static final Integer PRODUCT_ID_2 = 2;
#Test
public void getProduct() {
Product p1 = new PermProduct();
p1.setProductId(PRODUCT_ID_1);
Product p2 = new Product();
p2.setProductId(PRODUCT_ID_2);
List<Product> products = new ArrayList<Product>();
products.add(p1);
products.add(p2);
doReturn(false).when(partiallyMockedProductManager).isTempProduct(p1);
doReturn(true).when(partiallyMockedProductManager).isTempProduct(p2);
assertEquals(1, partiallyMockedProductManager.getPermProducts(products).size());
verify(partiallyMockedProductManager).isTempProduct(p1);
verify(partiallyMockedProductManager).isTempProduct(p2);
}
}

Your mockProductManager is actually not a mock but an instance of ProductManager class. You shouldn't mock a tested object. The way to mock some methods from tested object is using a spy but I recommend you to not use them, or even to not think about them unless you're fighting with some ugly legacy code.
I think your second 'when' should be replaced with assertion, like:
assertFalse(mockProductManager.isTempProduct(p1));
because what you really want to check in this test is if productManager.isTempProduct(p1) returns false for all instances of PermProduct. To verify results of some method calls/objects states you should use assertions. To make your life with assertions easier you can take a look on some helpful libraries like Hamcrest or FEST (http://docs.codehaus.org/display/FEST/Fluent+Assertions+Module). FEST is simpler for beginners I think.

Related

Why Mockito is calling real method?

I have a class Service that calls a method of singleton class. I would like to mock a saveContract method calls.
public class Service {
public Contract save(Contract contract) {
Contract result;
...
result = ContractDao.getInstance().saveContract(contract);
...
return result;
}
}
I modified Service class like this (added a field and a constructor, for testing purposes only):
public class Service {
private final ContractDao contractDao;
public Service() {
this(ContractDao.getInstance());
}
public Service(final ContractDao contractDao) {
this.contractDao = contractDao;
}
public Contract save(Contract contract) {...}
}
And my test class is:
#ExtendWith(MockitoExtension.class)
class ServiceTest {
#Mock
ContractDAO contractDaoMock;
private Service service;
#BeforeEach
public void setup() {
service = new Service(contractDaoMock);
}
#Test
void saveContractTest() {
Contract changedContract = new Contract(...);
when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
Contract givenContract = new Contract(...);
Contract actualContract = service.save(givenContract);
//Assertions
...
}
}
Add mockito-inline dependency and use the MockedStatic to mock the getInstance() method.
Your code should look like that:
#Test
void saveContractTest() {
Contract changedContract = new Contract(...);
try (MockedStatic<ContractDAO> mockedContractDAO = mockStatic(ContractDAO.class) {
mockedContractDAO.when(ContractDAO::getInstance).thenReturn(contractDaoMock);
when(contractDaoMock.saveContract(any())).thenReturn(changedContract);
Contract givenContract = new Contract(...);
Contract actualContract = service.save(givenContract);
//Assertions
...
}
}
Check the docs here to know a bit more about mocking static methods: https://javadoc.io/static/org.mockito/mockito-core/3.9.0/org/mockito/Mockito.html#static_mocks
In Service.save() I have not replaced the line
result = ContractDao.getInstance().saveContract(contract);
with line
result = contractDao.saveContract(contract);
So, we need to use a field instance which we mocked and not the singleton.getInstance().

How to check that a method is not being called using JUnit Mockito Verify

I have a class for which I am writing a JUnit test. I am trying to test if a particular method is never called.
public class CountryProcess extends AbstractCountryProcess {
private static final Logger log = LoggerFactory.getLogger(CountryProcessor.class);
private static final Long MAX_FILE = 20l;
#Override
protected boolean processCountry(Region region, City city) {
Long maxFile = region.getRequiredLongValue(SIZE);
if (maxFile < MAX_FILE) {
cntDao.addCountryLandMark(city);
}
else {
log.warn("File size was big");
}
return true;
}
And the test class is:
public class CountryProcessTest {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final CntDao cntDao = context.mock(CntDao.class);
#Before
public void setup() {
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
bind(cntDao.class).toInstance(cntDao);
}
});
}
#Test
public void shouldIgnoreIfFileSizeBiggerThanPermitted() {
//some code to make it trigger ELSE statement above...
verify(cntDao, never()).addCountryLandMark(anyString());
}
}
But this returns the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type $Proxy4 and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
Any idea how I can fix this in the current context. Please give an example using current code so I get a better idea?
You are mixing two mocking frameworks:
jMock - JUnitRuleMockery
Mockito - verify method
Clearly, they are not compatible with each other.
Your verify call looks ok, I believe it will work as soon as it receives a mock created with Mockito (Use Mockito.mock(CntDao.class))
As an alternative to never you can use Mockito.verifyNoMoreInteractions or Mockito.verifyZeroInteractions, but they are less specific.
In addition to the answer from #Lesiak, here is a reproducible example based on your code with both conditions tested and BDD implementation as well (commented out).
#ExtendWith(MockitoExtension.class)
class CountryProcessTest {
#Mock CountryDAO cntDao;
#Mock
Region region;
#Mock
City city;
#InjectMocks
CountryProcess countryProcess;
#Test
void processCountryLargeSize() {
// given
given(region.getRequiredLongValue()).willReturn(100L);
// when
countryProcess.processCountry(region, city);
// then
verifyNoInteractions(cntDao);
// then(cntDao).shouldHaveNoInteractions(); // BDD implementation
}
#Test
void processCountrySmallSize() {
// given
given(region.getRequiredLongValue()).willReturn(10L);
// when
countryProcess.processCountry(region, city);
// then
verify(cntDao).addCountryLandMark(city);
verifyNoMoreInteractions(cntDao);
// then(cntDao).should().addCountryLandMark(any()); // BDD implementation
// then(cntDao).shouldHaveNoMoreInteractions(); // BDD implementation
}
}
The rest of the classes here are provided for reference.
Region
public class Region {
private int size;
public Long getRequiredLongValue() {
return Integer.toUnsignedLong(size);
}
}
AbstractCountryProcess
public abstract class AbstractCountryProcess {
CountryDAO cntDao;
protected abstract boolean processCountry(Region region, City city);
}

Mockito mock java function with inner method

I have a class like so:
#Component
public class AddressConverter {
public Function<Address, AddressDTO> convertToDTO = new Function<Address, AddressDTO>() {
public AddressDTO apply(Address address) {
AddressDTO dto = new AddressDTO();
dto.setAddress1(address.getAddress1());
dto.setAddress2(address.getAddress2());
dto.setCity(address.getCity());
dto.setState(address.getState());
dto.setZip(address.getZip());
dto.setZip4(address.getZip4());
return dto;
}
};
}
I have another class that uses this like so:
#Component
public class ProfileConverter {
#Autowired
private AddressConverter addressConverter;
public Function<Profile, ProfileDTO> convertToDTO = new Function<Profile, ProfileDTO>() {
public ProfileDTO apply(Profile profile) {
ProfileDTO dto = new ProfileDTO();
dto.setEmployeeAddress(addressConverter.convertToDTO.apply(profile.getEmployeeAddress()));
return dto;
}
};
}
I am trying to mock the addressConverter class like:
EDIT: HERE IS THE TEST CLASS
public class ProfileConverterTest {
ProfileConverter converter;
AddressConverter addressConverter;
Profile profile;
ProfileDTO dto;
Address address;
AddressDTO addressDTO;
#Before
public void setUp() {
converter = new ProfileConverter();
addressConverter = Mockito.mock(AddressConverter.class);
profile = new Profile();
profile.setProfileId(123L);
dto = new ProfileDTO();
Mockito.when(addressConverter.convertFromDTO.apply(addressDTO)).thenReturn(address);
Mockito.when(addressConverter.convertToDTO.apply(address)).thenReturn(addressDTO);
ReflectionTestUtils.setField(converter, "addressConverter", addressConverter);
address = new Address("1","2","3","4","5","6");
address.setAddressId(123L);
addressDTO = new AddressDTO("hash","1","2","3","4","5","6");
}
#Test
public void applyReturnsProfileDTO() throws Exception {
ProfileDTO result = converter.convertToDTO.apply(profile);
assertEquals(result.getEmployeeAddress().getAddress1(), profile.getEmployeeAddress().getAddress1());
}
}
I keep getting a NullPointerException in my test on the first Mockito.when line. I am thinking it is caused by the mock addressConverter class calling a function calling an inner method. The function might be null?
You are expecting Mockito to call your class constructor which will initialize the field convertToDTO: this is not the case, and the simple test here demonstrate it:
#Test
public void test_that_yeepee_works() {
final Yeepee y = Mockito.mock(Yeepee.class);
Assertions.assertNotNull(y.myObject); // fails.
}
public static class Yeepee {
public Object myObject = new Object();
}
You might try Mockito.spy instead.
Or you need to explicitly do it:
converter = new ProfileConverter();
addressConverter = Mockito.mock(AddressConverter.class);
addressConverter.convertToDTO = (Function<Address, AddressDTO>) Mockito.mock(Function.class);
If you were using getters, Mockito might have done it for you using smart mocks.
I think, NPE is because you have not created a mock for AddressConverter class. You should write something like below:
AddressConverter addressConverter = Mockito.mock(AddressConverter.class);
Mockito.when(addressConverter.apply(any(Address.class))).thenReturn(addressDTO);
Note: any (Address.class) will match any object of Address class. If you want to test weather your address object is being used while calling (mocking) apply method, go ahead and add hashcode() and equals() implementation in your Address class.

How to mock another class method call from the method being tested using powermock-easymock?

I'm using easymock and powermock to write unit test case for the below isRegisteredUSer() of Class B. How to mock getUserInformation() of Class A and return a mocked UserAccessBean?
class A{
private int userId;
A(int userId){
this.userId = userId;
}
public UserAccessBean getUserInformation(){
UserAccessBean userAB = new USerAccessBean().findByUserId(userId);
return userAB;
}
}
Class B{
public static boolean isRegisteredUSer(int userId){
A a = new A(userId);
UserAccessBean userAB = a.getUserInformation();
if(userAB.getUserType().equals("R")){
return true;
}
return false;
}
JUnit
public class BTest extends EasyMockSupport{
UserAccessBean userAB = null;
A a = null;
int userId = 12345;
#Before
public void setUp() throws Exception {
userAB = new UserAccessBean();
}
#Test
public void when_UserDesctiptionIsR_Expect_True_FromIsRegisteredUser() throws Exception{
//data setup
userAB.setDescription("R");
A a = new A(12345);
EasyMock.expect(a.isRegisteredUser()).andReturn(userAB);
PowerMock.replayAll();
Boolean flag = B.isRegisteredUser(userId);
assertEquals(flag, true);
PowerMock.verifyAll();
}
}
Even If I use EasyMock.expect() to mock getUserInformation() method call, my console is going inside getUserInformation() when I run my JUnit.
Can someone please help me to mock another class functions method (Class A's getUserInformation) call from the method (Class B's isRegisteredUSer) being tested?
Please, next time copy actual working code. Your code has many typos and anomalies that makes it hard to workaround.
Nevertheless, I think you want a normal EasyMock for A and a mock on new for B. The code below should answer your question
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, B.class})
public class BTest extends EasyMockSupport {
UserAccessBean userAB = new UserAccessBean();
A a;
int userId = 12345;
#Test
public void when_UserDesctiptionIsR_Expect_True_FromIsRegisteredUser() throws Exception {
//data setup
userAB.setDescription("R");
A a = createMock(A.class);
expect(a.getUserInformation()).andReturn(userAB);
replayAll();
PowerMock.expectNew(A.class, userId).andReturn(a);
PowerMock.replay(A.class);
Boolean flag = B.isRegisteredUser(userId);
assertEquals(flag, true);
PowerMock.verifyAll();
verifyAll();
}
}
I will however highly recommend A to be injected into B and to get rid of the static method. That will get rid of PowerMock and simplify the code.

Mocking a List and attempting to iterate over it

Currently using Mockito to Test a method from one of my classes. My class contains a List, and the method takes in an object of the same class. The issue is when I attempt to iterate over the List from the object. I'm getting a null pointer to the list. Below you will see the code snippets.
private Shipment shipment;
private Shipment shipment2;
#Mock
private Order mockOrder1;
#Mock
private Order mockOrder2;
#Mock
private Order mockOrder3;
#Mock
private ArrayList<Order> mockShipmentOrders;
#Mock
private ArrayList<Order> mockShipmentOrders2;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockShipmentOrders.add(mockOrder1);
mockShipmentOrders.add(mockOrder2);
mockShipmentOrders2.add(mockOrder3);
shipment = new Shipment(1, mockShipmentOrders);
shipment2 = new Shipment(2, mockShipmentOrders2);
}
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
shipment.mergeShipments(shipment2);
assertEquals(3, shipment.getShipmentOrders().size());
}
above you can see my mockito test and below is my Class with the method:
public class Shipment {
private long shipmentID;
private List<Order> shipmentOrders;
public Shipment(long shipmentID, List<Order> shipmentOrders){
this.shipmentID = shipmentID;
this.shipmentOrders = shipmentOrders;
}
public List<Order> getShipmentOrders(){
return shipmentOrders;
}
public void mergeShipments(Shipment shipment2){
List<Order> existingShipment = shipment2.getShipmentOrders();
for (Order order : existingShipment){
shipmentOrders.add(order);
}
}
When I run the test I am getting a java.lang.NullPointerException for the line: for (Order order : existingShipment){
in mergeShipemts();
The question is; Is it possible to mock a list, call that list and then run a foreach over that mocked list?
There are some fundamental issues why your example not does work and throws a NullPointerException.
The call to add() on the mocked list effectively doesn't do anything. All void methods on mocks are "no-ops" by default
Iterating over a list using for-each syntax calls Collection.iterator() under the hood. This returns null, because you've not setup mockito to return anything else.
Instead, I would not mock the list and instead pass an actual list. Arrays.asList() is convenient for testing.
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
shipment = new Shipment(1, Arrays.asList(mockOrder1, mockOrder2));
shipment2 = new Shipment(2, Arrays.asList(mockOrder3));
}
If you're determined to mock a list then you'll have to mock its behaviour, i.e. making the add() actually store something and .iterator() return an iterator. This can be done rather painfully as follows. I've only included this to demonstrate the principle.
#Mock
private List<String> mockedList;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
List<String> realList = new ArrayList<>();
doAnswer(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocation) throws Throwable {
realList.add(invocation.getArgumentAt(0, String.class));
return null;
}
}).when(mockedList).add(any());
when(mockedList.iterator()).thenAnswer(new Answer<Iterator<String>>() {
#Override
public Iterator<String> answer(InvocationOnMock invocation) throws Throwable {
return realList.iterator();
}
});
mockedList.add("bar");
mockedList.add("baz");
}
#Test
public void iterateOverMockedList() {
for (String each : mockedList) {
System.out.println(each);
}
}
As #Adam says: "Iterating over a list using for-each syntax calls Collection.iterator() under the hood. This returns null because you've not setup mockito to return anything else."
So you have to setup mockito in this way;
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
//GIVEN
//Mock the iterator
Iterator<Order> stockIteratorMock = mock(Iterator.class);
//WHEN
//In setUp method you put two objs
when(mockShipmentOrder.size()).thenReturn(2);
//Set a mock for iterator
when(mockShipmentOrder.iterator()).thenReturn(iteratorMock);
// Instruct the iteratorMock when stop to return item
when(iteratorMock.hasNext())
.thenReturn(true)
.thenReturn(true)
.thenReturn(false);
// Instruct the iteratorMock what obj return on each call
// You can skip this: mockShipmentOrders.add(mockOrder1);
when(stockIteratorMock.next())
.thenReturn(mockOrder1)
.thenReturn(mockOrder2);
shipment.mergeShipments(shipment);
//THEN
assertEquals(2, shipment.getShipmentOrders().size());
}
This way is verbose, but you are free to modify the behaviour of the array list and also understand how it works under the wood.
You can't add values to the Mocked element. you can remove #Mock from the list of data and use new keyword to initilize it.
private Shipment shipment;
private Shipment shipment2;
#Mock
private Order mockOrder1;
#Mock
private Order mockOrder2;
#Mock
private Order mockOrder3;
private ArrayList<Order> mockShipmentOrders;
private ArrayList<Order> mockShipmentOrders2;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockShipmentOrders = new ArrayList<>();
mockShipmentOrders2 = new ArrayList<>();
mockShipmentOrders.add(mockOrder1);
mockShipmentOrders.add(mockOrder2);
mockShipmentOrders2.add(mockOrder3);
shipment = new Shipment(1, mockShipmentOrders);
shipment2 = new Shipment(2, mockShipmentOrders2);
}
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
System.out.println(shipment);
System.out.println(shipment2);
shipment.mergeShipments(shipment2);
assertEquals(3, shipment.getShipmentOrders().size());
}

Categories