I want to mock Order array class Order[].class. below mockMapper reads Order[].class and need to return Order[].class.
Service class
public class OrdersConnectorImpl {
public Order getOrderById(String Id, OrderType orderType) throws Exception {
Response response = null;
response = orderServiceTarget.queryParam("ID", Id).queryParam(ORDER_TYPE, orderType).request().accept(MediaType.APPLICATION_JSON)
.get();
final StatusType responseStatus = response.getStatusInfo();
final String serverResponseStr = response.readEntity(String.class);
if (responseStatus.equals(Response.Status.OK)) {
objectMapper = getObjectMapper(); // we have a private method in this class
Order[] orders = objectMapper.readValue(serverResponseStr, Order[].class);
if(orders.length>0) {
return orders[0];
}
}
}
}
Test class
public class OrdersConnectorImplTest {
private ObjectMapper mockMapper;
private class MockOrdersConnectorImpl extends OrdersConnectorImpl {
#Override
protected ObjectMapper getObjectMapper() {
return mockMapper;
}
}
}
#Test
public void test_getRenewalOrderForContract() throws Exception {
Response mockResponse = mock(javax.ws.rs.core.Response.class);
Order mockOrder = mock(Order.class);
when(mockResponse.getStatusInfo()).thenReturn(Status.OK);
when(mockResponse.readEntity(String.class)).thenReturn("{}");
when(mockBuilder.get()).thenReturn(mockResponse);
when(mockMapper.readValue("{}", Order[].class)).thenReturn(mockOrder); // this is the problem line
orderConnector.getOrderById("id", OrderType.NEW);
}
}
Please correct me here how to return expected.
You have autowired mockMapper which means, the actual object of ObjectMapper will be injected.
And in the when part, you setting up the behavior of mockMapper, which shouldn't be the case.
Edit 1
In your case, there is no need for mocking the Order class, you have to return the array Order which you can create in the tests.
For your information, with Junit there is no way, you can mock the object which is been created inside the method.
Related
I have instantiated a parametrized constructor here called request operation with dynamic values. how to #Autowire this to Requestclass? subsequently, in Request class, I have created a new RatingResponse how to #Autowire this as well?
class Initializer
public class Intializer
{
NewClass newclass = new NewClass();
String testName = Number + "_" + "Test"; -->getting the String number dynamically
Test test = new Test(testName); -> this is a different class
Operation operation = new RequestOperation(test, newclass ,
sxxx, yyy, zzz); - argumented constructor
opertaion.perform();
}
RequestClass
public class RequestOperation implements Operation {
// the constructor
public RequestOperation(Test test, Sheet reportSheet, XElement element, TestDataManager testDataManager, Report report)
{
this.test = test;
this.newclass = newclass ;
this.sxxx= sxxx;
this.yyy= yyy;
this.zzz= zzz;
}
#Override
public boolean perform(String CompanyName, String Province) {
Response response = new RatingResponse(this.test, this.reportSheet,
callService(this.buildRequest(CompanyName, Province)), this, this.report);-> create a new paramterizedconstructor
}
private String buildRequest(String CompanyName, String Province) {
return pm.getAppProperties().getProperty(constructedValue); }
}
**Response class **
public class RatingResponse implements Response {
public RatingResponse(Test test, Sheet reportSheet, Object obj, RequestOperation requestOperation, Report report) {
this.test = test;
if (obj instanceof Document) {
this.document = (Document) obj;
}
this.operation = requestOperation;
this.reportSheet = reportSheet;
this.report = report;
}
** interface **
#Component
public interface Operation {
public boolean perform(String Name, String Province);
}
#Component
public interface Response {
void construct();
}
In spring boot, you can autowire only types marked with #Bean or classes marked with #Component or its derivitives like #Service, #Controller
The speciality of these annotations is that only a single instance of the class is kept in memory.
So if your requirement needs you to create new classes for each set of new dynamic values, then autowiring them is not the right way to go.
However if you have limited number of possible dynamic values that your class can have, you can create beans for each of them like this
#Configuration
class MyBeans{
#Bean
public RatingResponse ratingResponse(){
Response response = new RatingResponse(this.test, this.reportSheet,
callService(this.buildRequest(CompanyName, Province)), this, this.report);
return response
}
}
Then in the class you need to use it, you can do
#Autowired
RatingResponse ratingResponse
I need to do unit testing of methods of Singleton class which internally uses RxJava Singles, and used PowerMock test framework to mock static class and methods. I tried various method to mock Schedulers.io() and AndroidSchedulers.mainThread() methods but it's not working. I'm getting java.lang.NullPointerException error at line .subscribeOn(Schedulers.io()) inside UserApi.verifyUserData() method.
Singleton Class UserApi (Class under Test)
final public class UserApi {
private CompositeDisposable compositeDisposable;
private String userID;
//private final SchedulerProvider schedulerProvider;
private UserApi(String userId) {
super();
this.userID = userId;
//this.schedulerProvider = schedulerProvider;
}
public static UserApi getInstance() {
return SingletonHolder.sINSTANCE;
}
private static final class SingletonHolder {
private static final UserApi sINSTANCE;
static {
String uuid = UUID.randomUUID().toString();
sINSTANCE = new UserApi(uuid);
}
}
// Rest Api call
public void verifyUserData(byte[] doc, byte[] img) {
this.compositeDisposable = new CompositeDisposable();
String docStr = Base64.encodeToString(doc, Base64.NO_WRAP);
String imgStr = Base64.encodeToString(img, Base64.NO_WRAP);
final Disposable apiDisposable = IdvManager.getInstance().getUserManager().verifyUserData(docStr, imgStr)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<JsonObject>() {
#Override
public void accept(JsonObject verifyResponse) throws Exception {
pollResult();
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable error) throws Exception {
// handle error code...
}
});
this.compositeDisposable.add(apiDisposable);
}
private void pollResult() {
// code here...
}
}
UserManager Class and Interface
public interface UserManager {
Single<JsonObject> verifyUserData(String docStr, String imgStr);
}
final class UserManagerImpl implements UserManager {
private final UserService userService;
UserManagerImpl(final Retrofit retrofit) {
super();
this.userService = retrofit.create(UserService.class);
}
#Override
public Single<JsonObject> verifyUserData(String docStr, String imgStr) {
// Code here...
}
}
Unit Test
#RunWith(PowerMockRunner.class)
#PrepareForTest({IdvManager.class, Base64.class, Schedulers.class, AndroidSchedulers.class, UserApi.class})
public class UserApiTest {
#Mock
public UserManager userManager;
#Mock
private Handler handler;
private IdvManager idvManager;
private Schedulers schedulers;
private UserApi spyUserApi;
private TestScheduler testScheduler;
private String userID;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
testScheduler = new TestScheduler();
handler = new Handler();
PowerMockito.suppress(constructor(IdvManager.class));
// mock static
PowerMockito.mockStatic(IdvManager.class);
PowerMockito.mockStatic(Schedulers.class);
PowerMockito.mockStatic(AndroidSchedulers.class);
PowerMockito.mockStatic(Base64.class);
// Create mock for class
idvManager = PowerMockito.mock(IdvManager.class);
schedulers = PowerMockito.mock(Schedulers.class);
PowerMockito.when(IdvManager.getInstance()).thenReturn(IdvManager);
when(idvManager.getUserManager()).thenReturn(userManager);
spyUserApi = PowerMockito.spy(UserApi.getInstance());
// TestSchedulerProvider testSchedulerProvider = new TestSchedulerProvider(testScheduler);
when(Base64.encodeToString((byte[]) any(), anyInt())).thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return java.util.Base64.getEncoder().encodeToString((byte[]) invocation.getArguments()[0]);
}
});
when(schedulers.io()).thenReturn(testScheduler);
when(AndroidSchedulers.mainThread()).thenReturn(testScheduler);
userID = UUID.randomUUID().toString();
}
#After
public void clearMocks() {
//Mockito.framework().clearInlineMocks();
}
#Test
public void verifyUserData_callsPollResult_returnsResponse() {
// Input
String docStr = "iVBORw0KGgoAAAANSUhEUgAAAJ4AAACeCAYAAADDhbN7AA.....";
// Output
JsonObject verifyResponse = new JsonObject();
verifyResponse.addProperty("status", "Response created");
doReturn(Single.just(verifyResponse)).when(userManager).verifyUserData(docStr, docStr);
// spy method call
spyUserApi.verifyUserData(docFrontArr, docFrontArr);
testScheduler.triggerActions();
// assert
verify(userManager).verifyUserData(docStr, docStr);
}
}
Error
java.lang.NullPointerException
at com.rahul.manager.UserApi.verifyUserData(UserApi.java:60)
at com.rahul.manager.UserApiTest.verifyUserData_callsPollResult_returnsResponse(UserApiTest.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
I'm not sure whether i can test methods of Singleton class by spying on real instance of Singleton class using PowerMock.
Testing your code is complex because it's not testable and it's not extensible. It contains hardcoded dependencies everywhere (e.g. user id, handler, several singletons).
If you decide to use another id generation approach or another handler, you won't be able to do this without rewriting whole class.
Instead of hardcoding dependencies, ask for them in constructor (for mandatory dependencies) or setters (for optional ones).
This will make your code extensible and testable. After you do this, you will see your class contains several responsibilities, after moving them into separate classes, you will get much better picture :-)
For example:
public UserApi(String userId, Handler handle) {
this.userId = userId;
this.handler = handler;
}
Schedulers.io() is a static method, so you need to use mockStatic (which you did) and define the related mock accordingly.
I rearranged your setup method a bit, to improve the readability and fixed the mistake. You do not need an instance of Schedulers (The variable you named schedulers).
Probably a simple typo you made, as you did the right thing for Base64 and AndroidSchedulers.
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
testScheduler = new TestScheduler();
handler = new Handler();
// mock for instance of `IdvManager`
PowerMockito.suppress(constructor(IdvManager.class));
idvManager = PowerMockito.mock(IdvManager.class);
when(idvManager.getUserManager()).thenReturn(userManager);
// mock for `IdvManager` class
PowerMockito.mockStatic(IdvManager.class);
PowerMockito.when(IdvManager.getInstance()).thenReturn(idvManager);
// mock for `Schedulers` class
PowerMockito.mockStatic(Schedulers.class);
when(Schedulers.io()).thenReturn(testScheduler);
// spy for instance of `UserApi`
spyUserApi = PowerMockito.spy(UserApi.getInstance());
// mock for `Base64` class
PowerMockito.mockStatic(Base64.class);
when(Base64.encodeToString((byte[]) any(), anyInt())).thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return java.util.Base64.getEncoder().encodeToString((byte[]) invocation.getArguments()[0]);
}
});
// mock for `AndroidSchedulers` class
PowerMockito.mockStatic(AndroidSchedulers.class);
when(AndroidSchedulers.mainThread()).thenReturn(testScheduler);
userID = UUID.randomUUID().toString();
}
However the NPE is missing the part that actually indicates its failing from this, consider adding it if that does not solve your problem.
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 can I mock this method below that calls another private static method?
public class testA {
public static JSONObject retrieveOrder(String orderId)
throws Exception {
String url = "/contract/";
JSONObject order = new JSONObject();
order.put("orderId", orderId);
return orderPOST(url, order);
}
private static orderPOST(String url, JSONObject order) {
return orderPOSTString(url, order.toString());
}
private static orderPOSTString (String url, String order) {
//do another call to method which will return JSONObject
}
}
How can I just mock retrieveOrder method only as I don't care any of those private methods? And as for those private static methods, I can't modify any of them so have to accept them as is.
This is my test:
#Test
public void testRetrieveOrderMethod() throws Exception {
String url = "/contract/";
JSONObject order = new JSONObject();
order.put("orderId", orderId);
PowerMockito.spy(testA.class);
PowerMockito.doReturn(url, order.toString()).when(testA.class, "orderPOST", Matchers.any(), Matchers.any());
JSONObject retrieved = testA.retrieveOrder("12345");
}
Please let me know if I miss anything here. I keep getting NullPointerException as I suspect it's actually calling those private methods.
In your code, when(testA.class, "orderPOST"... is mocking orderPost method.
If you want to mock just the retrieveOrder method and want to ignore the other ones, your test class should be:
#RunWith(PowerMockRunner.class) // needed for powermock to work
// class that has static method and will be mocked must be in PrepareForTest
#PrepareForTest({ testA.class })
public class MyTestClass {
#Test
public void testRetrieveOrderMethod() throws Exception {
// JSON object you want to return
JSONObject order = new JSONObject();
order.put("orderId", "whatever value you want to test");
PowerMockito.spy(testA.class);
// retrieveOrder will return order object
PowerMockito.doReturn(order).when(testA.class, "retrieveOrder", Mockito.anyString());
// call static method
JSONObject retrieved = testA.retrieveOrder("12345");
// do the assertions you need with retrieved
}
}
You could also change spy and doReturn to:
PowerMockito.mockStatic(testA.class);
Mockito.when(testA.retrieveOrder(Mockito.anyString())).thenReturn(order);
Both will work the same way.
I'm building a Java REST application with JAX-RS.
In the context of the application, I have the following bean classes:
public class ContentView {
// Field definitions, getters/setters
}
public class ArticleDetailView extends ContentView {
// more definitions, getters/setters
}
public class UpsellDetailView extends ContentView {
// more definitions, getters/setters
}
UpsellDetailView and ArticleDetailView have more attributes and they both extend ContentView. I've got all the mappers correctly wired up, so all the instances of each respective class gets all its properties set correctly. I don't use any extra mappers - object properties get deserialized based on the public getters in the respective bean classes.
SeriesDetailView is similar:
public class SeriesDetailView extends SeriesLiteView {
private List<Content> content;
#JsonIgnore //We don't want content appear on the Series detail page
public List<Content> getContent() {
return content;
}
public void setContent(List<Content> content) {
this.content = content;
}
}
Now, I have a REST resource class as follows:
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_FORM_URLENCODED})
#Path("/")
public class ApiSiteResource extends AbstractContentResource {
...
#GET
#Path("/series/{uuid}/contents")
public List<ContentView> getSessionsForSeries(#Context HttpServletRequest request, #Context HttpServletResponse response, #BeanParam ApiParams params) {
final SeriesDetailView series = seriesService.findByUuid(params.getUuid());
if (series == null) {
response.setStatus(SC_NOT_FOUND);
return null;
}
List<ContentView> contentViewList = contentMapper.map(series.getContent());
List<ContentView> results = contentViewList.stream().map(e -> mapContent(e, e.getUuid())).collect(Collectors.toList());
return results;
}
#GET
#Path("/contents/{uuid}")
public ContentView uniqueContent(#Context HttpServletRequest request, #Context HttpServletResponse response, #BeanParam ApiParams params) {
ContentView beanView = contentService.findByUuid(params.getUuid());
if (beanView == null) {
response.setStatus(SC_NOT_FOUND);
return null;
}
beanView = mapContent(beanView, params.getUuid());
return beanView;
}
private ContentView mapContent(ContentView beanView, String uuid){
if (ArticleType.TypeGroup.upsell.toString().equals(beanView.getType())) {
UpSell upsell = ((UpSell)contentService.findByUuidRaw(uuid));
beanView = (UpsellDetailView)upsellMapper.map(upsell);
rewriteBodyHtml(beanView, upsell.getBody());
}
else if (ArticleType.TypeGroup.article.toString().equals(beanView.getType()) ||
ArticleType.TypeGroup.audio.toString().equals(beanView.getType()) ||
ArticleType.TypeGroup.video.toString().equals(beanView.getType())) {
Article article = ((Article)contentService.findByUuidRaw(uuid));
beanView = (ArticleDetailView)articleMapper.map(article);
rewriteBodyHtml(beanView, article.getBody());
}
return beanView;
}
}
Now, here's the problem:
when I invoke /contents/{uuid} in the browser, I get fully deserialized correct content type json (Article or UpsellDetailView), but
when I invoke /series/{uuid}/contents, I get a list of short-form json elements corresponding to the ContentView structure.
I do confirm that the List results in getSessionsForSeries() is a list of correct types (Article or UpsellDetailView).
But I can't find for the life of mine why these don't get properly deserialized when in the List. What am I missing?
Here's the answer:
For some reason, List's serializer was messed up and was when serializing was defaulting to the declared content class (ContentView).
If anyone has an idea why I'd appreciate enlightment.
So, I had to use brute force and provide my own serialization (do note the method's response type is changed to String):
#GET
#Path("/series/{uuid}/contents")
public String getSessionsForSeries(#Context HttpServletRequest request, #Context HttpServletResponse response, #BeanParam ApiParams params) {
final SeriesDetailView series = seriesService.findByUuid(params.getUuid());
if (series == null) {
response.setStatus(SC_NOT_FOUND);
return null;
}
List<ContentView> contentViewList = contentMapper.map(series.getContent());
List<ContentView> results = contentViewList.stream()
.map(e -> mapContent(e, e.getUuid())).collect(Collectors.toList());
ObjectMapper objectMapper = new ObjectMapper();
try {
return objectMapper.writeValueAsString(results);
} catch (IOException e) {
response.setStatus(SC_INTERNAL_SERVER_ERROR);
return null;
}
}
Thanks to the tutorial here: http://www.davismol.net/2015/03/05/jackson-json-deserialize-a-list-of-objects-of-subclasses-of-an-abstract-class/