Unit test java Optional with mockito - java

I want to test a method which returns an Optional client in it.
I want to test the scenario when client is empty.This is not a working code but overall it looks like this
public Optional<String> doSomething(String place) {
Optional<Client> client = Optional.empty();
try {
client = Optional.ofNullable(clientHelper.get(place));
} catch (Ex ex) {
log.warn("Exception occured:", ex);
}
return client.isPresent() ? Optional.ofNullable(client.get().getPlaceDetails(place)) : Optional.empty();
}
I have a helper class clientHelper which returns a client based on place if exists, if not it throws exception.
For test, this is what I came up with
#Test
public void testClientHelper(){
ClientHelper clientHelper = Mockito.mock(ClientHelper.class);
Optional<Client> client = Optional.empty();
Mockito.when(Optional.ofNullable(clientHelper.get("IN"))).thenReturn(client);
assertEquals( doSomething("IN"), Optional.empty())
}
But it returns exception -
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Optional cannot be returned by get()
get() should return Client
I have been following this link Mockito error with method that returns Optional<T>

your problem here is that you are calling when with something that isn't a mock. You are passing it an Optional.
If I understand what you are trying to do here, the clientHelper is passed to the object with the doSomething method and you want to mock it for testing purposes. If that's the case it'd more typically look like this:
interface ClientHelper {
Client get(String place) throws Ex;
}
class ClassUnderTest {
private final ClientHelper clientHelper;
public ClassUnderTest(ClientHelper helper) {
this.clientHelper = helper;
}
public Optional<String> doSomething(String place) {
try {
return Optional.ofNullable(clientHelper.get(place).getPlaceDetails(place));
} catch (Ex ex) {
log.warn("Exception: " + ex);
return Optional.empty();
}
}
}
#Test
void testFullHelper() {
Client client = mock(Client.class);
when(client.getPlaceDetails("IN")).thenReturn("Details");
ClientHelper helper = mock(ClientHelper.class);
when(helper.get("IN")).thenReturn(client);
ClassUnderTest obj = new ClassUnderTest(helper);
assertEquals("Details", obj.doSomething("IN"));
}

Related

Method with Optional return type returns null value

I have the two methods as defined below.
public Optional<String> getSomething(final String input) throws ContainerException {
try{
return Optional.of(globals.getParam(GlobalsClass.Keys.SOME_ID).strict().stringValue());
} catch(ContainerException e) {
log.error(e);
throw e;
}
}
#Test
public void test_get_something() {
try {
final Optional<String> something = client.getSomething("24430881");
if(something.isPresent()) {
System.out.println(something.get());
}
} catch (ContainerException e) {
Assert.fail("Should not have thrown any exception");
}
}
The problem is that I am getting a NullPointerException for something.isPresent() as something is null. Shouldn't it be Optional.empty()? Can't get why a null value is returned by getSomething().
Since you invoke getSomething from the unit test I'd guess that client is a Mock and you forgot to explicitly mock it's method like following:
// with Mockito
when(client.getSomething(any(String.class)))
.thenReturn(Optional.of("someResponse"));
When you don't do it then Mock's method returns null (not Optional.empty()!) by default

EasyMock still goes into implementation of a method mocked with addMockedMethod

I am trying to write a unit-test in Java. Due to the structure of Java class, I have to come up with a way in which whenever a constructor of a class is called, a mocked object of that class is created. I want to mock 2 methods of that class.
CallToBeMocked mockCallToBeMocked = EasyMock.createMockBuilder(CallToBeMocked.class)
.withConstructor(ArgumentA.class, ArgumentB.class, ArgumentC.class)
.withArgs(mockArgumentA, mockArgumentB, mockArgumentC)
.addMockedMethod("isProxied", ArgumentA.class)
.addMockedMethod("remoteCall", String.class, ArgumentA.class, Object.class)
.createMock();
EasyMock.expect(mockCallToBeMocked.isProxied(mockArgumentA)).andReturn(false);
EasyMock.expect(mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null)).andThrow(new Exception()).times(3);
The problem is that although I have clearly specified that isProxied and remoteCall methods have to be mocked and I have given appropriate expectations for those methods, it still starts going into the actual implementations of these methods.
It should perfectly work. So something else is going on. Here is a working example based on your code. What's different from your actual implementation?
public class PartialTest {
public interface ArgumentA { }
public interface ArgumentB { }
public interface ArgumentC { }
public static class CallToBeMocked {
public CallToBeMocked(ArgumentA a, ArgumentB b, ArgumentC c) {
}
public boolean isProxied(ArgumentA a) {
return true;
}
public int remoteCall(String ip, ArgumentA a, Object any) throws Exception {
return 0;
}
}
#Test
public void test() throws Exception {
ArgumentA mockArgumentA = createNiceMock(ArgumentA.class);
ArgumentB mockArgumentB = createNiceMock(ArgumentB.class);
ArgumentC mockArgumentC = createNiceMock(ArgumentC.class);
CallToBeMocked mockCallToBeMocked = createMockBuilder(CallToBeMocked.class)
.withConstructor(ArgumentA.class, ArgumentB.class, ArgumentC.class)
.withArgs(mockArgumentA, mockArgumentB, mockArgumentC)
.addMockedMethod("isProxied", ArgumentA.class)
.addMockedMethod("remoteCall", String.class, ArgumentA.class, Object.class)
.createMock();
expect(mockCallToBeMocked.isProxied(mockArgumentA)).andReturn(false);
expect(mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null)).andThrow(new Exception()).times(3);
replay(mockCallToBeMocked);
assertFalse(mockCallToBeMocked.isProxied(mockArgumentA));
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
try {
mockCallToBeMocked.remoteCall("ip-address", mockArgumentA, null);
fail("Should throw");
} catch (Exception e) { }
verify(mockCallToBeMocked);
}
}
If we aren't tied to EasyMock, here's a way in which the same functionality can be achieved using Mockito.
import static org.mockito.Mockito.verify;
import org.mockito.Mockito;
....
ClassToBeMocked myMock = Mockito.mock(ClassToBeMocked.class);
Mockito
.when(myMock.isProxied(any(ArgumentA.class)))
.thenReturn(false);
Mockito
.when(myMock.remoteCall(any(String.class), any(ArgumentA.class), any(Object.class)))
.thenThrow(new Exception("monkeys"));
<USE ``myMock``>
verify(myMock, times(1)).isProxied(mockArgumentA);
verify(myMock, times(3)).remoteCall("ip-address", mockArgumentA, null);

PowerMockito Enum in Switch Statement throwing NPE

I'm testing a class with PowerMockRunner which retrieves a value ENUM from a static method in a helper class. A null pointer is thrown when this value ENUM is passed into a SWITCH statement in the classUnderTest.
I've debugged and can see the ENUM is set correctly (name, type, ordinal all as expected) so am unsure as to why the NPE is thrown. Anybody encounter similar issue?
Note: PowerMockito is required as classUnderTest includes calls to private methods. Below is complete example with a lot of code (unrelated to issue) removed. Comments added at point where ENUM is set and NPE is thrown
ClassUnderTest:
public class TestService extends BaseXAServiceBean
{
#Override
public ValueObject runExecute(ValueObject param) throws RemoteException, ServiceException
{
try
{
ValueEnum value = ValueServiceHelper.getValueType(param1(),
param2());
// value populated successfully with ENUM at this point
// NPE thrown when value is passed into below switch
switch (value)
{
case VALUE1:
{
// logic here...
break;
}
case VALUE2:
{
// logic here...
break;
}
case VALUE3:
{
// logic here...
break;
}
}
}
catch (ServiceException e)
{
throw e;
}
catch (Exception e)
{
throw new ServiceException(e, AppErrorCodes.INT.SL06, AppErrorCodes.SL06.E04);
} finally {
// clean up
}
}
}
Helper Class with static method:
public class ValueServiceHelper
{
public static ValueEnum getValueType(String param1, String param2) throws ServiceException
{
ValueEnum retVal = ValueEnum.VALUE3;
// proxy is mocked
ProductProxy proxy = ProxyFactory.createFactory("1").getProductProxy();
try
{
if (proxy.isValue1(param2))
{
retVal = ValueEnum.VALUE1;
}
else if (proxy.isValue2(param2))
{
retVal = ValueEnum.VALUE2;
}
}
return retVal;
}
}
Test Class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProxyFactory.class})
public class ValueTest {
#Spy
#InjectMocks
private TestService service = new TestService();
#Mock
private ProxyFactory proxyFactory;
#Mock
private Proxy proxy;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(ProxyFactory.class);
}
#Test
public void testSuccess() throws Exception {
// given
// when
PowerMockito.when(ProxyFactory.createFactory("1")).thenReturn(proxyFactory);
PowerMockito.when(proxyFactory.getProductProxy()).thenReturn(proxy);
PowerMockito.when(proxy.isValue1(param2)).thenReturn(true);
PowerMockito.when(proxy.isValue2(param2)).thenReturn(true);
service.runExecute(request);
// then
}
}
This is an issue with PowerMock that has existed since at least 2015. The only way to fix it that I'm aware of is to use if statements instead of a switch.

Java - How to test exception which never will occur?

I have Utils class with method which throws exception when given data are incorrect.
I have also Service which uses this method, but the data are always generated in way that they will be correct during call. Data are generated by another utils class.
I understand that I should throw this exception from Utils class - but I can't throw it from Service - so I have to catch it.
How can I test this, simulate this exception?
All actions on this data are in private methods.
I want to avoid PowerMock, because I heard that it's a sign of bad design.
So the question is, how to implement this in good design?
From your description it looks like this:
class Service {
public void someMethod() {
Data data = AnotherUtils.getData();
try {
Utils.method(data); // exception never thrown
} catch(Exception e) {
// how to test this branch?
}
}
}
The goal would be something like this:
interface DataProvider {
Data getData();
}
interface DataConsumer {
void method(Data data);
}
class Service {
private final DataProvider dataProvider;
private final DataConsumer dataConsumer;
public Service(DataProvider dataProvider, DataConsumer dataConsumer) {...}
public void someMethod() {
Data d = dataProvider.getData();
try {
dataConsumer.method(data);
} catch(Exception e) {
}
}
}
This technique is called dependency injection.
Then, when testing, you can simply provide a mock implementation for this DataProvider interface that does return faulty data:
#Test(expected=Exception.class)
public void myTest() {
DataProvider badDataProvider = () -> new BadData(); // Returns faulty data
Service service = new Service(badDataProvider, Utils.getConsumer());
service.someMethod(); // boom!
}
For the non-testing code, you could simply wrap the utils classes you already have in these interfaces:
class AnotherUtils {
public static Data getData() {...}
public static DataProvider getProvider() {
return AnotherUtils::getData;
}
}
...
Service service = new Service(AnotherUtils.getProvider(), Utils.getConsumer());
Here is an approach where you want to introduce Dependency Injection, but for whatever reason you don't want to change legacy code.
Say you have some static utility method like so:
class Utils{
public static Something aMethod(SomethingElse input) throws AnException{
if(input.isValid())
return input.toSomething();
throw new AnException("yadda yadda");
}
}
And you have a class that uses that utility method. You can still inject it with a FunctionalInterface.
#FunctionalInterface
interface FunctionThrowsAnException<K,V> {
V apply(K input) throws AnException;
}
class Service {
private final FunctionThrowsAnException<SomethingElse,Something> func;
Service(FunctionThrowsAnException<SomethingElse,Something> func){
this.func = func;
}
Something aMethod(SomethingElse input){
try{
return func.apply(input);
}catch(AnException ex){
LOGGER.error(ex);
}
}
}
Then use it like this:
new Service(Utils::aMethod).aMethod(input);
To test it:
new Service(x -> { throw new AnException("HA HA"); }).aMethod(input);

Mockito and jUnit for mocking utilities with REST

Code:
public class AccountService(){
private ObjectMapper mapper = new ObjectMapper();
public Account getAccount(){
try {
ClientResponse response = RestUtility.getAccounts();
if(CLientResponse.OK.Status == response.getClientResponseStatus()){
return mapper.readValue(response.getEntity(String.class), Account.class)
}
} catch(Exception e){
log.error(e.getMessage(), e);
}
return null;
}
}
How can I mock this service? The RestUtility is a static utility and cannot be mocked by mockito. All I want is for my method to return a list of 'mock' accounts. Is it even possible with this architecture?
To mock statick method you cna use PowerMock.
Or you can create wrapper on your RestUtility class.
Reference to this wrapper should be provided on constructor.
If you change to
public class AccountService() {
protected ClientResponse getResponse() { return RestUtility.getAccounts(); }
public Account getAccount() {
try {
ClientResponse response = getResponse();
...
}
}
it is trivial to mock out getResponse() using Mockito or other mock frameworks. Or even easier:
public class AccountServiceTest {
class TestableAccountService extends AccountService {
#Override
protected ClientResponse getResponse() { return <yourmockresponsegoeshere>; }
}
#Test
public void testMe() {
AccountService ac = new TestableAccountService();
assertThat( ac.getAccount.size() , equalTo( 1 ) );
// etc
...
}
Cheers,

Categories