Inject private field to tested method - java

Simple question, I have a class with have a List field with Items, I have a method operating on that List, checking if there is a Item with a name given in parameter and returning true or false. I would like to test that method, creating an ArrayList in test class, mocking JdbcItemDao class, and calling a method. Method in test cannot reach an array, how to fix it? Code:
public class JdbcItemDao {
private List<Item> tempStockList;
public JdbcItemDao() {
this.tempStockList = getAllStockItems();
//getting items from my sql, returning them as ArrayList
}
public boolean checkStockItems(String itemName) {
for (Item item : tempStockList) {
if (item.getItemName().equalsIgnoreCase(itemName)) {
return true;
}
}
return false;
}}
Test class:
public class JdbcTest {
JdbcItemDao jdbcItemDao;
List<Item> tempStockList;
#Before
public void setup() {
jdbcItemDao = mock(JdbcItemDao.class);
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
}
#Test
public void checkStockItemsName() throws Exception {
assertTrue(jdbcItemDao.checkStockItems("LEDTv"));
}}

If you cannot refactor i guess your left with creating a private class, overriding the method and using that class for testing:
public class JdbcTest {
List<Item> tempStockList = new ArrayList<>();
#Before
public void setup() {
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
}
#Test
public void checkStockItemsName() throws Exception {
JdbcItemDao jdbcItemDao = new CustomJdbcItemDao();
assertTrue(jdbcItemDao.checkStockItems("LEDTv"));
}
private class CustomJdbcItemDao extends JdbcItemDao{
#Override
public List<Item> getAllStockItems(){
return tempStockList;
}
}
}

You use the wrong kind of test double. You need a spy (which is a wrapper around the real implementation) instead of a mock (which is a subclass overriding all methods of the mocked class):
jdbcItemDao = spy(new JdbcItemDao());
tempStockList = new ArrayList<>();
tempStockList.add(new Item(1, "LEDTv", new BigInteger("40"),
new Integer("3"), new BigInteger("70")));
doReturn(tempStockList).when(jdbcItemDao).getAllStockItems();
Off cause this only works if you move
this.tempStockList = getAllStockItems();
out of the constructor...

There is a method 'getAllStockItems', it is in JdbcItemDao.java class
public List<Item> getAllStockItems() {
return jdbcTemplate.query(SELECT_ALL_STOCK_ITEMS, itemRowMapper);
}
It is getting a data from MySQL database, so that's why i would like to use fake Array in tests.

Related

Flink Filter function Testing

I am trying to find the way to test RichFilter function just like RichMappFunction like present here : RichMapFunction Testing is present here......Searched through internet and find nothing...Please help...
public class Person{
public String name;
public Int age;
}
public class OCRKafkaFilter extends RichFilterFunction<Person> {
#Override
public boolean filter(Person person) {
return person.age>21;
}
}
How can we write a test case for this rich filter function for stateful operators ...
You can up a test harness for a filter function doing something like this:
private OCRKafkaFilter function;
private OneInputStreamOperatorTestHarness<Person, Person> harness;
#BeforeEach
void setUpHarness() throws Exception {
function = new OCRKafkaFilter();
StreamFilter<Person> operator = new StreamFilter<>(function);
harness = new OneInputStreamOperatorTestHarness<>(operator);
harness.open();
}
In the example you gave, the RichFilterFunction isn't stateful. In that case you can write tests like this:
public class FilterFunctionTest {
#Test
public void testFilter() {
OCRKafkaFilter filter = new OCRKafkaFilter();
Person person21 = new Person(21);
Person person22 = new Person(22);
assertEquals(false, filter.filter(person21));
assertEquals(true, filter.filter(person22));
}
}

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.

junit - how to mock field in real class?

I have a tricky situation. I am using MVP architecture for android but thats not important. I have a class called DoStandardLoginUsecase that basically just connects to a server with login info and gets a access token. i am trying to test it. But the problem is the context that i am passing in to it so i can initialize dagger.
public class DoStandardLoginUsecase extends BaseUseCase {
#Inject
UserDataRepository mUserDataRepo;
private StandardLoginInfo loginInfo;
public DoStandardLoginUsecase(Context context) {
/* SEE HERE I AM USING A APPLICATION CONTEXT THAT I PASS TO DAGGER
*/
((MyApplication)context).getPresenterComponent().inject(this);
}
#Override
public Observable<Login> buildUseCaseObservable() {
return mUserDataRepo.doStandardLogin(loginInfo);
}
public void setLoginInfo(StandardLoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
}
and here is the test i have so far:
public class DoStandardLoginUsecaseTest {
DoStandardLoginUsecase standardLoginUsecase;
StandardLoginInfo fakeLoginInfo;
TestObserver<Login> subscriber;
MockContext context;
#Before
public void setUp() throws Exception {
//now when i create the object since its a mock context it will fail when it tries to call real things as these are stubs. So how do i test this object. how do i create an instance of this object ? I am willing to use [daggerMock][1] if that helps also.
standardLoginUsecase = New DoStandardLoginUsecase(context);
fakeLoginInfo = new StandardLoginInfo("fred#hotmail.com","Asdfgh4534");
subscriber = TestObserver.create();
}
#Test
public void buildUseCaseObservable(){
standardLoginUsecase.seLoginInfo(fakeLoginInfo);
standardLoginUsecase.buildUseCaseObservable().subscribe(subscriber);
subscriber.assertNoErrors();
subscriber.assertSubscribed();
subscriber.assertComplete();
}
}
I would do the test like this:
public class DoStandardLoginUsecaseTest {
private DoStandardLoginUsecase target;
private MyApplication contextMock;
#Before
public void beforeEach() {
contextMock = Mockito.mock(MyApplication.class);
// Note that you need to mock the getPresenterComponent
// but I don't know what it returns.
target = new DoStandardLoginUsecase(contextMock);
}
#Test
public void buildUseCaseObservable() {
UserDataRepository userDataMock = Mockito.mock(UserDataRepository.class);
StandardLoginInfo loginInfoMock = Mockito.mock(StandardLoginInfo.class);
target.mUserDataRepo = userDataMock;
target.setLoginInfo(loginInfoMock);
Observable<Login> expected = // create your expected test data however you like...
Mockito.when(userDataMock.doStandardLogin(loginInfoMock)).thenReturn(expected);
Observable<Login> actual = target.buildUseCaseObservable();
Assert.areSame(actual, expected);
}
}

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