Testing surrounding try catch method with mockito - java

Im figuring out, how to test this method and force the exception "DataAccessResourceFailureException", but i didn't have a valid way to do it.
I need to force that exception at "ProductRepositoryImpl" class. Any ideas?
ProductRepositoryImpl
#Override
public Product saveProduct(Product input) {
try {
return productRepositoryAdapter.saveProduct(input);
} catch (DataAccessResourceFailureException e) {
logger.error(ERROR_WHEN_SAVING_PRODUCT_DATA_DETAIL + e.getMessage());
}
return null;
}
ProductRepositoryAdapter
public Product saveProduct(Product input) throws DataAccessResourceFailureException {
ProductData productData = UtilTransform.productToProductData(input);
// This method throws exception when there's no connection
Product createdProduct = productDataRepository.findSkuByCountry(input.getSku(),
input.getCountry());
if (createdProduct == null) {
return Product.fromModel(productDataRepository.save(productData));
} else {
logger.error(THE_PRODUCT_ALREADY_EXISTS_IN_THE_RECORDS);
}
return null;
}
ProductDataRepository
public interface ProductDataRepository extends MongoRepository<ProductData, String> {
#Query("{'sku': ?0, 'country': ?1}")
public Product findSkuByCountry(String sku, String country);
public Optional<ProductData> findById(ProductId id);
}
And my Test, Im using mockito.
#Test
void saveProductException() {
Mockito.when(productRepository.saveProduct(buildProduct())).thenReturn(buildProduct());
Mockito.when(adapter.saveProduct(buildProduct())).
thenThrow(DataAccessResourceFailureException.class);
Assertions.assertThrows(DataAccessResourceFailureException.class,
() -> productRepository.saveProduct(buildProduct()));
}
Error:
org.opentest4j.AssertionFailedError: Expected org.springframework.dao.DataAccessResourceFailureException to be thrown, but nothing was thrown.
EDIT.
I change a little bit my approach, with this code (thanks guys) i was able to throw the exception so my code it will return null. After that checking my jacoco index.html i can see that "exception" its covered successfully.
#Test
void saveProductException() {
Product product = buildProduct();
Mockito.when(adapter.saveProduct(product)).
thenThrow(DataAccessResourceFailureException.class);
Assertions.assertNull(productRepository.saveProduct(product));
}

This seems suspect:
Mockito.when( productRepository.saveProduct(buildProduct()) ).thenReturn(buildProduct());
. . .
Assertions.assertThrows(DataAccessResourceFailureException.class,
() -> productRepository.saveProduct(buildProduct()) );
You're saying, when productRepository.saveProduct(buildProduct()) is called then return buildProduct() but then you assert that when it's called it should throw DataAccessResourceFailureException?
Instead maybe try this:
#Test
void saveProductException() {
// as NicoVanBelle recommends, ensure you're referencing the same product throughout this test
Product product = buildProduct();
Mockito.when(adapter.saveProduct(product).thenThrow(DataAccessResourceFailureException.class);
// Also as NicoVanBelle points out, when your `adapter` throws, `saveProduct` will return `null`
Assertions.assertThat(productRepository.saveProduct(product)).isNull();
}

I suspect 2 things here
You have setup the productRepository.saveProduct to not to throw and then you assert it throw the exception
Assertions.assertThrows(DataAccessResourceFailureException.class, () -> productRepository.saveProduct(buildProduct()));
You are calling buildProduct() which I assume returns the new product but mockito tries to check the argument equality so takeout it as Product myProduct = buildProduct() and use myProduct
#Test
void saveProductException() {
Product myProduct = buildProduct();
Mockito.when(productRepository.saveProduct(myProduct))
.thenThrow(DataAccessResourceFailureException.class);;
Mockito.when(adapter.saveProduct(buildProduct())).
thenThrow(DataAccessResourceFailureException.class);
Assertions.assertThrows(DataAccessResourceFailureException.class,
() -> productRepository.saveProduct(myProduct));
}

Related

Return .map lambda with function that throws exception

Is there any way to use mapping optional entity as shown below when the function called in lambda throws an exception and when it does I want to pass this exception to function that called getFieldHives in first place, IDE force me to wrap it in try/catch block and when trying to throw it again i end up with loop of try/catch. Or perhaps there is other way of approaching this issue, my main goal is to avoid using optionalFieldDAO.isPresent() and optionalFieldDAO.get().
public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException {
Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id);
return optionalFieldDAO
.map(fieldDAO -> createFieldHivesResponse(fieldDAO, user))
.orElseThrow(() -> new FieldNotFoundException("Field not found!"));
}
private List<HiveResponse> createFieldHivesResponse(FieldDAO fieldDAO, UserDAO user) throws FieldNotOwnedException {
if(!user.getFieldDAOList().contains(fieldDAO)) throw new FieldNotOwnedException("Field not owned!");
//rest of code
}
Optional field can contain empty value(in case of null) or value. but your method return type is list. so you need to collect values in a list
public List<HiveResponse> getFieldHives(String token, Long id) throws UserNotFoundException, FieldNotFoundException {
Optional<FieldDAO> optionalFieldDAO = fieldRepository.findById(id);
List<HiveResponse> hiveResponses = new ArrayList<>();
optionalFieldDAO.ifPresent(dao-> {
hiveResponses.addAll(createFieldHivesResponse(dao,user));
});
return hiveResponses;
}
private List<HiveResponse> createFieldHivesResponse(FieldDAO fieldDAO, UserDAO user) throws FieldNotOwnedException {
if(!user.getFieldDAOList().contains(fieldDAO)) throw new FieldNotOwnedException("Field not owned!");
//rest of code
}

Avoiding code duplication when checking for default responses

I have a Java program that calls an external API (RealApi in the code below) and sometimes I want to avoid calling this API and instead return pre-constructed responses (generated by FakeApi).
So, I ended up duplicating this kind of construct in most of my methods:
public Type1 m1(String s) {
try {
Type1 r = FakeApi.m1(s);
if (r != null) {
return r;
}
} catch (Exception e) {
// log error
}
return RealApi.m1(s);
}
What are some options to avoid duplicating this try/catch block everywhere? It's important that if FakeApi throws an exception or returns null, the RealApi must be called.
One option would be encapsulate the error checking behaviour into its own method:
public <T> T fakeOrReal(Supplier<T> fake, Supplier<T> real) {
try {
T r = fake.get();
if (r != null) {
return r;
}
}
catch (Exception e) {
// log error
}
return real.get();
}
You can then just call it with
public Type1 m1(String s) {
return fakeOrReal(() -> FakeApi.m1(s), () -> RealApi.m1(s));
}
This is not as simple as Thomas Preißler's answer but it will help you not repeat any method at all. So if you expand the interface, you have to modify only the concrete classes and not the linker which describes the actual behavior you want.
Create an interface that contains all the methods of RealApi:
interface Api {
Type1 m1(String s);
}
Then a class that does the actual call:
class ConcreteApi implements Api {
public Type1 m1(String s) {
return RealApi.m1(s);
}
}
Then create your FakeApi:
class TotallyFakeApi implements Api {
public Type1 m1(String s) {
return FakeApi.m1(s);
}
}
Now, the tricky part to avoid repeating yourself:
private static Object callImplementation(Api api, Method method, Object[] methodArgs) throws Exception {
Method actualMethod = api.getClass().getMethod(actualMethod.getName(), actualMethod.getParameterTypes());
return actualMethod.invoke(api, methodArgs);
}
Api fakeOrReal(Api fakeApi, Api realApi) {
return (Api) Proxy.newProxyInstance(
FakeApi.class.getClassLoader(),
new Class[]{Api.class},
(proxy, method, methodArgs) -> {
try {
Object r = callImplementation(fakeApi, method, methodArgs);
if (r != null) {
return r;
}
} catch (Exception e) {
// logError(e);
}
return callImplementation(realApi, method, methodArgs);
}
);
}
Get the actual implementation like this:
Api apiToUse = fakeOrReal(new TotallyFakeApi(), new ConcreteApi());

java Mockito verify abstract method

i have an issue on verifying a call to method of class under test, using the verify() method it tells that the call is not done to that method, this method is defined as abstract in super class (loadFile(String))
find bellow the code :
public abstract class FileParser {
public Iterator<String> loadFile(FileSettingsToSend fileSetting) {
System.out.println("file before staged");
try {
if(!movFile("staged",fileSetting))
return null;
System.out.println("file after move "+fileSetting.getFile().getAbsolutePath());
boolean isValidFormatFile = fileValidator.checkFileFormat(fileSetting);
if (!isValidFormatFile) {
System.out.println("file format is not valid");
return null;
}
return readBlock(fileSetting);
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
} finally {
}
//return null;
}
public abstract Iterator<String> readBlock(FileSettingsToSend fileSettingsToSend)
throws JsonProcessingException, IOException;
}
public class JsonFileParser extends FileParser {
public final ObjectMapper mapper = new ObjectMapper();
#Autowired
public JsonFileParser(FileValidator jsonFileValidatorService, FileAttributeService fileAttributeService) {
super(jsonFileValidatorService, fileAttributeService);
}
#Override
public Iterator<String> readBlock(FileSettingsToSend fileSetting) throws JsonProcessingException, IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println("inside readBlock json implementation");
List<String> listAttribute = fileAttributeService.getAttributes(fileSetting.getDiretoryPath());
String[] blocDelimitor = fileAttributeService.getDelimitorRepositpry(fileSetting.getDiretoryPath());
System.out.println("after validator");
final JsonNode root = mapper.readTree(fileSetting.getFile());
if (root == null)
return null;
Iterator<JsonNode> nodeIterator = root.elements();
System.out.println("Data is " + root);
return new Iterator<String>() {
JsonNode node;
#Override
public boolean hasNext() {
return nodeIterator.hasNext();
}
#Override
public String next() {
int i = 0;
node = nodeIterator.next();
System.out.println("after nex " + node.toString());
Arrays.stream(blocDelimitor).forEach(e -> {
node = node.path(e);
System.out.println("inside next " + node.toString());
});
String result = null;
if (node.isArray()) {
System.out.println("It is Array");
for (JsonNode node1 : node) {
if (i != 0)
result = result + "," + listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
else
result = listAttribute.stream().map(e -> e + "=" + node1.get(e))
.collect(Collectors.joining(","));
i++;
}
} else
result = listAttribute.stream().map(e -> e + "=" + node.get(e)).collect(Collectors.joining(","));
return result;
}
};
}
Test method is :
#Mock
FileValidator jsonFileValidatorService;
#Mock
FileAttributeService fileAttributeService;
JsonFileParser jsonFileParserMock = new JsonFileParser(jsonFileValidatorService, fileAttributeService);
#Test
public void validatorNotTrue() throws JsonProcessingException, IOException{
when(jsonFileValidatorService.checkFileFormat( anyObject() )).thenReturn(true);
JsonFileParser jsonFileParser = Mockito.spy(jsonFileParserMock);
doReturn(true).when(jsonFileParser).movFile(anyString(),anyObject() );
assertNull(jsonFileParser.loadFile(null));
verify(jsonFileParser, times(1)).movFile(anyString(),anyObject());
assertTrue(jsonFileParser.movFile(anyString(), anyObject()));
assertTrue(jsonFileValidatorService.checkFileFormat( anyObject() ));
//exception.expect(Exception.class);
verify(jsonFileParser,times(1)).readBlock(anyObject();
}
#BeforeClass
public static void settingUp(){
}
#Before
public void initMock(){
MockitoAnnotations.initMocks(this);
}
the line verify(jsonFileParser,times(1)).readBlock(anyObject(); return false; meaning that the method loadFile of jsonfileParser not called
can you get your held to tell why it is not called.
Thank you.
This happens because you initialize the mocks after you create a JsonFileParser. Note that #Before method is executed after all the fields of your test class are initialized.
As a result, you pass null dependencies to the class. The invocation to the null FileValidator throws NullPointerException, but you swallow it in your catch block.
Generally it is advisable to verify the arguments you pass to your constructors and methods, to fail fast in case of an error. For example, Java comes with a handy Objects::requireNonNull method to verify that the passed parameters are non-null.
Similarly it's generally a bad practice to swallow every single exception. For instance, in your example, you expect IOException and JsonProcessingException to be thrown. It's better to catch these explicitly and let the program crash (or at least log a warning) for any other one.
Finally, mocks and spies are prone to overuse. Usually, it's enough to use fakes - dummy implementations of your interfaces. Depending on how much control you have over the code, you may also want to refactor it to avoid using a spy at all. Using one in a code you may freely change may signal an architectural problem.

handling return from function where no return type is expected in some case in java

I had writtern a piece of code:In this code we are calling validitem function to check if passes param is some valid item or not.If it is valid item,i want to return that item else i want to abort processing stating its not valid item.Please suggest solution for the initial code writtern below, on how to handle situation where we dont want to return anything.And if we return null,then how and where to have exception catching?
public void constructdata(){
String foo = validitem(param);
//code to avoid processing if null is returned
}
public validitem(String item){
if(item.equals("Apple"){
return item;
}
if(item.equals("Ball"){
return item;}
return null;
}
If you want validitem() still to return null and if so, throw an exception:
String foo = validitem(param);
if ( foo != null ) {
container.putField(key, foo);
} else {
throw new Exception();
}
If you want to make validitem() only return a valid value and throw an exception otherwise:
public void constructdata(){
try {
container.putField(key, validitem(param));
} catch (Exception e) {
// Handle exception
}
}
public validitem(String item) throws Exception {
if (item.equals("Apple") {
return item;
}
if (item.equals("Ball") {
return item;
}
throw new Exception("Error message");
}
You should use a more specific exception than Exception(). I've only used it to demonstrate the logic.
Avoid returning null when possible because it can lead to bugs, insted you can return a Java8 Optional. If you are not using java8 there is an equivalent in the guava library. Returning an Optional forces the client to think about how to handle the case where nothing is returned.

Mockito defining 'when' invokes the answer

I need to mock a JDBC update statement, and I want to make sure that the update string sent is the correct one. I have a MockConnectionManager that has the following method defined for defining the expected query strings:
public void setUpdateExpectedQuery(String ...expectedQueryStrings) throws SQLException {
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String str = Arrays.toString(invocationOnMock.getArguments());
throw new RuntimeException("Update string is not as expected: " + str);
}
});
for(String expected : expectedQueryStrings) {
when(mockStatement.executeUpdate(expected)).then(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
// Do something, just don't throw an exception here.
return null;
}
});
}
}
I want that if an unexpected query string was encountered an exception will be thrown. The query strings we expect are below as mentioned in the Mockito wiki (http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#2).
For some reason, when executing the test and just calling the setUpdateExpectedQuery, an exception is thrown.
MockConnectionManager connectionManager = (MockConnectionManager) context.getBean("connectionManager");
connectionManager.setUpdateExpectedQuery("INSERT WHATEVER INTO WHENEVER");
The same exception as written in the first Answer: java.lang.RuntimeException: Update string is not as expected: [INSERT WHATEVER INTO WHENEVER]
How is this possible? is calling 'when' actually invokes the method? I never saw it happening in other cases...
I suspect the problem is that your calls within the loop (when you call mockStatement.executeUpdate(expected)) match your earlier mock of when(mockStatement.executeUpdate(anyString())).
Remember that the way the mock knows what you're calling within the when is because you're calling it - imagine translating when(mockStatement.executeUpdate(anyString())) into:
int result = mockStatement.executeUpdate(anyString());
OngoingStubbing<Integer> tmp = when(result);
tmp.then(...);
It may be that you just need to have a single when(...) call. So:
public void setUpdateExpectedQuery(String ...expectedQueryStrings)
throws SQLException {
final Set<String> capturedQueries = new HashSet<>
(Arrays.asList(expectedQueryStrings);
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String query = (String) invocationOnMock.getArguments[0];
if (capturedQueries.contains(query)) {
return null;
}
throw new RuntimeException("Update string is not as expected: " + query);
}
});
}

Categories