Mocking a new object inside another method testing - java

I have a class which contains method like
private MqttWrapper createNewMqttWrapperInstance(EdamsCell deviceCell) {
MqttWrapper mqttWrapper = new MqttWrapper();
MqttClientConnectionManager mqttClientConnectionManager = context.getMqttClientConnectionManager();
MqttClientConnection mqttClientConnection = mqttClientConnectionManager.getMqttClientConnection(mqttWrapper);
setMqttWrapperProperties(mqttWrapper, AWSIotConnectionStatus.CONNECTED);
log.info("New instance of MqttWrapper created for device cell {}", deviceCell);
return mqttWrapper;
}
My test method is
try(MockedConstruction mocked = mockConstruction(MqttWrapper.class, (mock, context) -> {})){
mockMethodCalls();
doReturn(mqttClientConnection).when(mqttClientConnectionManager).getMqttClientConnection(); ->I am not able to control this as there in code a new object is passed.
mqttWrapperFactoryImpl = spy(new MqttWrapperFactoryImpl(context));
outputMqttWrapper = mqttWrapperFactoryImpl.getMqttWrapperForSiteId(SITE_ID);
assertEquals(expectedMqttWrapper, outputMqttWrapper);
// verify(mqttClientConnectionManager, times(1)).getMqttClientConnection(IOT_ENDPOINT, deviceResponseListener,
// CELL, new MqttWrapper());
verify(mqttClientConnectionManager, times(1)).getMqttClientConnection( sample);
verifyNoMoreInteractions(mqttClientConnectionManager);
}
I want to mock this b object creation so that I can control the methodC and verify the same after assertion. I dont want to use PowerMockito.
I can't control the invocation method also, neither I am able to verify the test calling.
I tried MockitoConstruction but was unable to do so.

Mockito framework can be used to mock the creation of the B object by mocking the behavior of the constructor;
B mockB = Mockito.mock(B.class);
Mockito.whenNew(B.class).withNoArguments().thenReturn(mockB);
yourObject.methodA();
Mockito.verify(yourObject).methodC(mockB);

Related

How do I test parallelStream().map(interface_impl -> method(interface_impl)0.collect(Collectors.toList()) with Mockito's whens?

So I am creating a unit test utilising Mockito.
A component of the code I'm testing looks like this:
public Object validateObject(final Parameter param) {
Object validated_object = new Object();
final List<Object> processed_objects = interface_impl_list.parallelStream()
.map(interface_impl -> parallelTask(interface_impl))
.collect(Collectors.toList());
for (final Object object : processed_objects) {
validated_object = object;
if (Object.getResult == PASSED) {
break;
}
}
return validated_object;
private Object parallelTask(InterfaceObj interface_impl) {
return validate_object(interface_impl);
}
Our teams 'template' for unit tests would look something like this:
#Spy
private List<InterfaceObj> interface_impl_list;
#Mock
private InterfaceImpl1 interface_impl_1;
#Mock
private InterfaceImpl2 interface_impl_2;
#BeforeEach
void setup() {
interface_impl_list.add(interface_impl_1);
interface_impl_list.add(interface_impl_2);
}
#Test
void myTest() {
// Variables needed
final int x = 1
// Return variables
...
// when()'s
// Not sure how to do this for parallelStream
when(interface_impl1.method()).thenReturn(returnVariable1); //i.e. within validateObject()
when(interface_impl2.method()).thenReturn(returnVariable1);
// Method being tested
final Object object = classBeingTested.findWillToGoOn(x);
// verify()'s
verify(interface_impl1, times(2)).method();
verify(interface_impl2, times(2)).method();
// assertions
...
}
I can't seem to find any examples of someone using whens or general unit testing examples for parallelStream.forEach().map().collect() that I can apply here.
How would I go about this? Is there any examples people could even point to?
Thanks in advance
So the parallelStreams is a recent addition. Previously the code would just call the parallelTask consecutively so I would just add when's in order of when that external class method was called.
I played around with doing when(interface_impl_list.parallelStreams.map().collect(Collectors.toList())) and some variations but I can't get past any intial compile errors and figure out how to go about it.
Edit: Error Message without mocking/adding when for the stream or any of the map or collect methods
java.lang.NullPointerException at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:327)

Test an overridden method of an inner class with JUnit and Mockito

I have a method in a class I need to test. The method uses an external class that I need to mock, so the external class doesn't get tested or executes its dependencies. The special challenge is: one method of the external class gets overridden. Method looks like this:
public void fetchLocalData(final String source, final ObservableEmitter<String> destination) {
final List<String> options = Arrays.asList("recursive","allFiles","includeDir");
// This class comes from a package
final DirScan dirscan = new DirScan(source, options) {
#Override
protected Action getResult(final String result) {
destination.onNext(result);
return Action.Continue;
}
};
dirscan.scan();
destination.onComplete();
}
I tried:
DirScan scanner = mock(DirScan.class);
when(scanner.scan()).thenReturn("one").thenReturn("two");
That didn't work. What do I miss? How would I need to refactor to make this testable?
If you want to replace the dirscan with a mock (or a spy) you'll need to refactor your class that it's a dependency or parameter. Alternatively you could use PowerMockito's whenNew functionality.
Lets assume you change your class and instead of the String source you provide the DirScan object as a parameter. You would need to have some kind of creation method for dirscan elsewhere (might be a static method).
final List<String> options = Arrays.asList("recursive","allFiles","includeDir");
public DirScan createDirScan(String source) {
// This class comes from a package
final DirScan dirscan = new DirScan(source, options) {
#Override
protected Action getResult(final String result) {
destination.onNext(result);
return Action.Continue;
}
};
return dirscan;
}
public void fetchLocalData(final DirScan dirscan, final ObservableEmitter<String> destination) {
dirscan.scan();
destination.onComplete();
}
Juding from your question you seem to want to test the interaction with the destination object, so you do not want to mock the dirscan object (because if you do there won't be any interaction). You might want to use a spy and only replace the getResult method.
In your test now you could then simply pass a spy for the dirscan object and
define the behaviour of it with thenAnswer.
final ObservableEmitter<String> destination = ...
DirScan dirscan = Mockito.spy(createDirScan(source, destination));
Mockito.when(dirscan.getResult(Mockito.any(String.class))).thenAnswer((Answer<Action>) invocation -> {
String result = invocation.getArgument(0);
destination.onNext(result);
return Action.Continue;
});
classUnderTest.fetchLocalData(dirscan, destination);
At this point you might notice that its probably better to not use a spy and just use the real DirScan object. Using the spy to do what you intend to do with the overriden method looks like overkill to me.
The real object has to work for this test to be of value, so you might as well test the real thing.

How to mock methods in dynamically loaded jars

I have a class called Price with constructor, which I am dynamically loading via reflection:
public Price(Context context, String pair) {
this.context = context;
this.value1 = pair.substring(0, 3);
this.value2 = pair.substring(3, 6);
this.dps = context.getService().getm1(value1, value2).getm2();
}
However I want to mock the Context object
and I want
context.getService().getm1(value1, value2).getm2()
to return 5.
Here is what I have tried
//mocking the Context class
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
constructor =contextClass.getConstructor();
Object context = Mockito.mock(contextClass);
//trying to instantiate the Price class
Class<?> priceClass = urlClassLoader.loadClass("com.algo.Price");
constructor = priceClass.getConstructor(contextClass,String.class);
Mockito.when(context.getService().getm1(value1, value2).getm2().thenReturn(5));
Object price = constructor.newInstance(context,"PRICES");
However I have a red line under
context.getService()
The error says
The method getService() is undefined for the type Object
How can I get around this, my end goal is to create the Price object with the variable
dps
being an int 5, that is why I want to mock the Context object.
For me the only way is to implement your whole test using reflection which is really laborious especially in your case as you will need to do the same thing for each method call as you cannot mock directly context.getService().getm1(value1, value2).getm2().
Assuming that I have a class Context as below
public class Context {
public int getm1(String value1, String value2) {
return -1;
}
}
A normal test case would be:
#Test
public void normal() throws Exception {
Context context = Mockito.mock(Context.class);
Mockito.when(context.getm1(Mockito.anyString(), Mockito.anyString())).thenReturn(5);
Assert.assertEquals(5, context.getm1("foo", "bar"));
}
The same test using reflection would be:
#Test
public void reflection() throws Exception {
... // Here I get the classloader
// Get the class by reflection
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
// Mock the class
Object context = Mockito.mock(contextClass);
// Get the method by reflection
Method method = contextClass.getMethod("getm1", String.class, String.class);
// Invoke the method with Mockito.anyString() as parameter
// to get the corresponding methodCall object
Object methodCall = method.invoke(context, Mockito.anyString(), Mockito.anyString());
// Mock the method call to get what we expect
Mockito.when(methodCall).thenReturn(5);
// Test the method with some random values by reflection
Assert.assertEquals(5, method.invoke(context, "foo", "bar"));
}
Cannot really understand this issue. If you are working with an unknown type it cannot be typed as Context within the construtor.
But independently, an approach would be to create interfaces representing the expected structure of context and then mock the interfaces to return the value.
It is not necessary to really load the dynamic class within the test if it is mocked either way.

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

Can one use Mockito to mock org.jibx.runtime.BindingDirectory?

I'm writing unit tests for my Java app and I need to write a test for a potential JiBX exception that can be thrown. The method I'm testing calls on a method from another class, where the JiBX exception can be potentially thrown. This is the class I'm testing (let's call it Class A):
#Inject
private CommonDAL commonDAL;
#Async
public Future<String> getTransactionalXXXAvailability(
List<XXXAvailRequestEntry> requestEntries, TravelWindow travelWindow) {
if (requestEntries.size() == 0)
return null;
XXXAvailRqAccessor requestAccessor = new XXXAvailRequestBuilder().buildRequest(requestEntries, travelWindow);
logger.info(requestAccessor.marshalRequest());
String responseAsXml = null;
try {
responseAsXml = getResponse(requestAccessor.getRequest());
} catch (JiBXException e) {
logger.error("Problem unmarshaling the XXX avail response: ", e);
}
logger.info(responseAsXml);
return new AsyncResult<String>(responseAsXml);
}
private String getResponse(OTAXXXAvailRQ request) throws JiBXException {
HbsiConnectionInfo connectionInfo = new HbsiConnectionInfo();
connectionInfo.useConnectionInfoFromContext();
HBSIXML4OTAWebserviceSoap hbsiSoap = getHbsiSoapService(connectionInfo);
InterfacePayload header = new InterfacePayload();
header.setChannelIdentifierId("XXXXXXXXX");
header.setVersion("2005B");
header.setInterface("HBSI XML 4 OTA");
ComponentInfo componentInfo = new ComponentInfo();
XXXAvailRqAccessor requestAccessor = new XXXAvailRqAccessor(request);
componentInfo.setId(requestAccessor.getFirstXXXCode());
componentInfo.setUser( connectionInfo.getUsername() );
componentInfo.setPwd( connectionInfo.getPassword() );
componentInfo.setComponentType(EComponentType.XXX);
Login login = new Login();
login.setComponentInfo(componentInfo);
Message body = new Message();
// todo: this needs to be unique for every request.
// todo: hook up to logging
body.setRequestId(UUID.randomUUID().toString());
body.setTransaction(ETransaction.XXX_AVAIL_RQ);
body.setXML(requestAccessor.marshalRequest());
return hbsiSoap.getSoapRequest(header, body, login);
}
HBSIXML4OTAWebserviceSoap getHbsiSoapService(HbsiConnectionInfo connectionInfo) {
HBSIXML4OTAWebservice ws = new HBSIXML4OTAWebservice( connectionInfo.getWsdlLocation() );
HBSIXML4OTAWebserviceSoap hbsiSoap = ws.getHBSIXML4OTAWebserviceSoap();
Map<String, Object> requestContext = ((BindingProvider)hbsiSoap).getRequestContext();
String readTimeout = commonDAL.getPropertyValue(new PropertyKey(Section.HBSI,
Property.HBSI_WS_READ_TIMEOUT));
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, Integer.parseInt(readTimeout));
String connectionTimeout = commonDAL.getPropertyValue(new PropertyKey(Section.HBSI,
Property.HBSI_WS_CONNECTION_TIMEOUT));
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, Integer.parseInt(connectionTimeout));
return hbsiSoap;
}
The method that throws the error is as follows (and from another class, let's call it Class B):
public String marshalRequest() {
StringWriter requestAsXml = new StringWriter();
try {
IBindingFactory bindingFactory = BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);
IMarshallingContext marshalingContext = bindingFactory.createMarshallingContext();
marshalingContext.setIndent(2);
marshalingContext.setOutput(requestAsXml);
marshalingContext.marshalDocument(request);
} catch (JiBXException e) {
logger.error("Problem marshaling PROTECTEDCLASSNAME.", e);
}
return requestAsXml.toString();
}
When "body.setXML(requestAccessor.marshalRequest());" is called, another class (requestAccessor) is visited by the test, and it's method .marshalRequest is where the JiBX exception is supposed to be thrown. The purpose of the tests I'm writing is to get this Class A's unit test coverage to 100&, but the system under test is composed of at least two classes as I can't mock XXXAvailRqAccessor object called requestAccessor. I can't get any tests to produce this error, for the following reasons.
The XXXAvailRqAccessor object called requestAccessor is instantiated inside the methods I'm testing so I can't use a mock to throw an exception.
the OTAXXXAvailRQ argument passed to .getResponse() cannot be mocked because it's created by the builder for XXXAvailRqAccessor.
I tried spying on IBindingFactory, but it didn't work. I created a method in Class B that would instantiate an IBindingFactory so I could spy on it, but that didn't work.
I also tried using PowerMock to return a mock XXXAvailRqAccessor when it is instantiated, however when I attempted to mock a JiBXExceptioin for .getRequest, Mockito said "Checked exception is invalid for this method". If I can't get Mockito to throw this error, I don't know if it's possible to manipulate the associated objects to throw it.
Well not really, or I don't know of such way at least. You could, if you REALLY want to do it (I'm against it) create a method like this in that class:
IBindingFactory getBindingFactory() {
return BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);
}
And replace this line:
IBindingFactory bindingFactory = BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);
With:
IBindingFactory bindingFactory = getBindingFactory();
Then you can spy() (you can read on Mockito.spy() in the documentation if you're not familiar with it) this object and make this method return a mock. From that point it's smooth sailing.
This approach is not adviced though because:
you are creating a new method (a useless one) just for testing
said method has to be visible for testing so you cannot mark it as private...
I'm not a huge fan of spies in general
The question remains: how to properly test such cases. Well in most situations I try to refactor as much as possible and sometimes it helps. And in other cases... Well I still did not come up with a better solution.
As I said in my comment, I fully advocate Mateusz's solution. But there is an alternative. In the class that has the marshalRequest method, have a private final field of type IBindingFactory. Also in this class, have a package-private constructor with one extra argument, that is, the IBindingFactory to set. The normal constructor will call BindingDirectory.getFactory( ... ) then call the new constructor. So, if the standard constructor has a single String argument, the class might look like this.
public class MyClass{
private String name;
private IBindingFactory bindingFactory;
public MyClass(String name){
this(name, BindingDirectory.getFactory(PROTECTEDCLASSNAME.class));
}
MyClass(String name, IBindingFactory bindingFactory){
this.name = name;
this.bindingFactory = bindingFactory;
}
public String marshalRequest() {
StringWriter requestAsXml = new StringWriter();
try {
IMarshallingContext marshalingContext = bindingFactory.createMarshallingContext();
marshalingContext.setIndent(2);
marshalingContext.setOutput(requestAsXml);
marshalingContext.marshalDocument(request);
} catch (JiBXException e) {
logger.error("Problem marshaling PROTECTEDCLASSNAME.", e);
}
return requestAsXml.toString();
}
}
The reason for doing this is so that in the test for your class, you can create a mock IBindingFactory, and pass it in to the package-private constructor.

Categories

Resources