I am trying a JUNIT class, which uses calls an interface in which a method 'generateexcelreport' , builds an excel reprot based on a list of values.But when I used mockito to mock the implementation, I am getting an exception with creating a file, no w I tried using the Mockito.doNothing() on this method , but still Mockito calls the method and am getting the exception again.
Exception:
java.lang.NullPointerException: Cannot invoke "java.io.File.mkdir()" because the return value of "java.io.File.getParentFile()" is null
My Method:
public void generateExcelReport(HashMap<String, List<Object>> hydrated) throws IOException, InvalidFormatException{
Workbook workbook = new XSSFWorkbook();
hydrated.entrySet().stream().forEach(key -> {
List<Object> bodyNode = (List<Object>) key.getValue().get(0);
Sheet sheet = workbook.createSheet(key.getKey().toString());
try {
buildExcel(bodyNode,workbook,sheet);
} catch (IOException | InvalidFormatException e) {
e.printStackTrace();
}
});
try {
File report= new File(fileName);
FileOutputStream fileOut = null;
if (hydrationReport.getParentFile().mkdir()) {
fileOut = new FileOutputStream(hydrationReport);
workbook.write(fileOut);
}else if(Files.exists(Path.of(hydrationReport.getParent()))){
fileOut = new FileOutputStream(hydrationReport);
workbook.write(fileOut);
}else {
throw new IOException("Failed to create directory " + hydrationReport.getParent());
}
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
And this is myy mock class, I am stuck creating it, Could someone please help
public class ExecutorImplTest {
#InjectMocks
ExecutorImpl impl;
#Test
public void vlaidateHydrationTest() throws TimeoutException, IOException, InvalidFormatException {
///when
HashMap<String, List<Object>> map = impl.validateHydration(request);
}
}
Related
I have a class that stores Excel workbooks:
private Map<String, Workbook> workbooks = new HashMap();
public Workbook createWorkbook(String name) {
Workbook workbook = new XSSFWorkbook();
workbooks.put(name, workbook);
return workbook;
}
and a method that writes into a workbook with a specified name:
public void write(List<ExcelData> data, String workbookName) {
Workbook workbook = workbooks.get(workbookName);
CreationHelper createHelper = workbook.getCreationHelper();
... write stuff
FileOutputStream fileOut = new FileOutputStream(workbookName + ".xlsx");
workbook.write(fileOut);
fileOut.close();
workbook.close();
}
However when I try to call method write two times for the same workbook:
testExcel.write(data, "Default");
testExcel.write(data1, "Default");
I get
Exception in thread "main" java.io.IOException: Cannot write data, document seems to have been closed already
error. I know I can open existing Excel workbook like this:
FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(inputStream);
But I was wondering if there's a way to bypass it by storing a Workbook variable. What are the inner mechanics at play? Is the variable becomes invalid after workbook.write() is called?
Instead of storing the workbook itself you can store the name of work book in list
private List<String> workbooks = new ArrayList();
Rewrite the createWorkbook to store only the name of the excel sheet
Rewrite the write method so it creates a new workbook as follows
public void write(List<ExcelData> data, String workbookName) {
Workbook workbook = new XSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
... write stuff
FileOutputStream fileOut = new FileOutputStream(workbookName + ".xlsx");
workbook.write(fileOut);
fileOut.close();
workbook.close();
}
This error mainly occurs when we try to write the contents of already closed workbook.
public void writeToExcel(File file) throws IOException {
LOGGER.debug("Writing chunks data to excel {}", file);
try (FileOutputStream outputStream = new FileOutputStream(file)) {
workbook.write(outputStream);
} catch (IOException e) {
LOGGER.error("Exception raised while writing chunks of items {}", e.getLocalizedMessage());
} finally {
// This line will take of closing XSSFWorkbook along with SXSSFWorkbook
workbook.close();
}
}
This code is the one is throwing the following exception
Exception thrown is:
Exception raised while writing chunks of items
"Cannot write data, document seems to have been closed already"
Why we were getting this exception?
Have a look at this code
private void instructionSheet(Resource resource) {
try {
InputStream in = resource.getInputStream();
// This is try-with-resources block which is closing the XSSFWorkbook
try (XSSFWorkbook xssfwb = new XSSFWorkbook(OPCPackage.open(in))) {
workbook = new SXSSFWorkbook(xssfwb);
}
} catch (IOException | InvalidFormatException e) {
LOGGER.error("The instruction sheet failed to create {}", e.getLocalizedMessage());
}
}
You can notice that the second try block is try-with-resources block and is closing the workbook, Hence we were getting the exception.
We resolved it just by removing the second try block i.e
private void instructionSheet(Resource resource) {
try {
workbook = new SXSSFWorkbook(new XSSFWorkbook(OPCPackage.open(resource.getInputStream())));
} catch (IOException | InvalidFormatException e) {
LOGGER.error("The instruction sheet failed to create {}", e.getLocalizedMessage());
}
}
You can notice in the first code block of this answer that we are closing the work book after writing the content to the file.
The close method called at finally block will take care of closing XSSFWorkbook instance along with SXSSFWorkbook.
I've an already works code to read an excel file. At first, the API in the controller clase receive the file as MultipartFile type. Then, because of some reasons, I need to convert the MultipartFile into File type. Here is the code:
private static File convert(MultipartFile file) throws IOException {
try {
File convertedFile = new File(file.getOriginalFilename());
convertedFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convertedFile);
fos.write(file.getBytes());
fos.close();
return convertedFile;
} catch (IOException e) {
e.printStackTrace();
throw new IOException("Error in converting the file with error message: " + e.getMessage());
}
}
Here is the service class which called in the controller, which call the convert method above:
public void create(MultipartFile file) throws Exception {
try {
File newFile = convert(file);
// rest of code
} catch (Exception e) {
// rest of code
}
}
Before I try to call the service in a new thread, code above works fine. But, when I try to call the service in a new thread, like below code, it says java.io.FileNotFoundException (The system cannot find the file specified), and the main problem is in this line fos.write(file.getBytes());. Here is how I create the new Thread in the controller:
#RequestMapping(method = RequestMethod.POST, value = "uploadfile")
public ResponseEntity<?> create(#RequestParam (value = "file", required = false) MultipartFile file) throws Exception {
try {
// ...other process
// ================================== code below not work
Thread create;
create = new Thread() {
public void run() {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}
};
create.start();
// ================================== code below not work
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}
});
t1.start();
// ================================== code below not work
new Thread(() -> {
try {
service.create(file);
} catch (Exception e) {
e.printStackTrace();
}
}){{start();}};
// ...rest of code
} catch (Exception e) {
// ...rest of code
}
}
above is several way how I try to make the thread but none of them works, result with same execption.
Objective: In short, I want to make the file reading in background and immediately send response to client after the service called.
Spring supports async way by return a Callable object. the pseudo code is like:
#RequestMapping(method = RequestMethod.POST, value = "uploadfile")
public Callable<ResponseEntity<?>> create(#RequestParam (value = "file", required = false) MultipartFile file) throws Exception {
return () -> {
try {
service.create(file);
return ResponseEntity.ok()
} catch (Exception e) {
return ResponseEntity.error( /*some error*/
e.printStackTrace();
}
};
}
Here's a tutorial reference : https://niels.nu/blog/2016/spring-async-rest.html .
another reference: How to make a async rest with Spring?
I am trying to update a file with some value. But there are few junk values are also getting updated with the original content while saving. Using the below code.
public class WriteToFile{
public static void main(String[] args){
Path path = Paths.get("C:\\someFile.txt");
String fileContent = new String("someText");
if (Files.exists(path)) {
final File filePath = new File("C:\\someFile.txt");
try {
FileUtils.writeFile(filePath,fileContent);
} catch (final Exception e1) {
// TODO What if writing to the state file fails??
}
}
}
public class FileUploadUtils {
public static void writeFile(final File filePath, final Object
byteFileContent) {
try (FileOutputStream fileOutputStream = new FileOutputStream(filePath);
ObjectOutputStream out = new ObjectOutputStream(fileOutputStream)) {
out.writeObject(byteFileContent);
} catch (final IOException io) {
io.printStackTrace();
}
}
}
I am able to write the content to file also, but it is adding some junk characters also. like "’ t SomeText"
The ObjectOutputStream seems to add some values while writing the data to the file.
Why won't you directly use the FileOutputStream you created and pass the data as bytes ?
public static void main(String[] args) {
Path path = Paths.get("C:\\someFile.txt");
String fileContent = new String("someText");
if (Files.exists(path)) {
final File filePath = new File("C:\\someFile.txt");
try {
FileUploadUtils.writeFile(
filePath, fileContent.getBytes());
} catch (final Exception e1) {
// TODO What if writing to the state file fails??
}
}
}
public class FileUploadUtils {
public static void writeFile(final File filePath, final byte[] byteFileContent) {
try (FileOutputStream fileOutputStream = new FileOutputStream(filePath)) {
fileOutputStream.write(byteFileContent);
} catch (final IOException io) {
io.printStackTrace();
}
}
}
I have a piece of code with try-catch block:
public static void writeExcelToFile(String outFileName, HSSFWorkbook workBook) throws IOException{
File file = null;
FileOutputStream fileOutputStream = null;
try {
file = getFileByFileName(outFileName);
File parent = file.getParentFile();
Path filePath = parent.toPath();
if (Files.notExists(filePath) && !parent.mkdirs()) {
throw new IOException("Couldn't create dir: " + parent);
}
fileOutputStream = new FileOutputStream(file);
workBook.write(fileOutputStream);
} catch (FileNotFoundException fileNotFoundException) {
LOGGER.error("File path is invalid, file not found ", fileNotFoundException);
throw fileNotFoundException;
} catch (IOException ioException) {
LOGGER.error("Exception occured while reading writing file ", ioException);
throw ioException;
} catch (Exception exception) {
LOGGER.error("Exception occured ", exception);
throw exception;
} finally {
if (fileOutputStream != null) {
fileOutputStream.close();
}
}
file.setWritable(true);
}
I have written the following Junit for the catch block:
//#1: FileNotFoundException
#Test(expected = java.io.FileNotFoundException.class)
public void testWriteExcelToFileException() throws IOException {
PowerMockito.mockStatic(KnewtonCIExcelWriter.class);
PowerMockito.doThrow(new java.io.FileNotFoundException()).when(KnewtonCIExcelWriter.class);
KnewtonCIExcelWriter.writeExcelToFile(anyString(), anyObject());
}
//#2: IOException
#Test(expected = IOException.class)
public void testWriteExcelIOException() throws IOException {
PowerMockito.mockStatic(KnewtonCIExcelWriter.class);
PowerMockito.doThrow(new IOException()).when(KnewtonCIExcelWriter.class);
KnewtonCIExcelWriter.writeExcelToFile(anyString(), anyObject());
}
//#3: Exception
#Test(expected = Exception.class)
public void testWriteExcelException() throws IOException {
PowerMockito.mockStatic(KnewtonCIExcelWriter.class);
PowerMockito.doThrow(new Exception()).when(KnewtonCIExcelWriter.class);
KnewtonCIExcelWriter.writeExcelToFile(anyString(), anyObject());
}
However, only the last, #3 Junit passes. #1 and #2 gives java.lang.AssertionError: Expected exception: java.io.FileNotFoundException and java.lang.AssertionError: Expected exception: java.io.IOEXception.
Question: 1) How to get the #1 and #2 JUnit passing? 2) Am I catching the
correct exceptions?
powermockito syntax on doThrow when should be
when(KnewtonCIExcelWriter.class, "your method", argument (you can user matcher));
I am trying to write data into new row each time the function is called in selenium webdriver
I have written the function as below
public class ExcelFunctions
{
XSSFSheet sh;
int i=0;
public boolean entertestcaseinexcel(String tcnumber, String description, String value) throws IOException
{
boolean status = true;
try
{
XSSFRow row = sh.createRow(i);
row.createCell(0).setCellValue(tcnumber);
row.createCell(1).setCellValue(description);
row.createCell(2).setCellValue(value);
i++;
}
catch(Exception e)
{
status = false;
}
return status;
}
}
I am calling the above function here
import Selenium.ExcelFunctions;
public class ExcelWrite {
public static void main(String[] args) throws IOException
{
ExcelFunctions EF = new ExcelFunctions();
File file = new File("D:\\Selenium_Training\\SeleniumNewFile.xlsx");
FileInputStream fis = new FileInputStream(file);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sh = wb.getSheetAt(0);
EF.entertestcaseinexcel("TC001", "Successfully Logged in", "Pass");
FileOutputStream fout = new FileOutputStream(file);
wb.write(fout);
fout.close();
}
}
The problem is i am able to run the script but i am not getting any value written to the excel.
Could you please help, thanks in advance.
You have hard coded the cell number value in entertestcaseinexcel function. Take that value from the caller of your method. below is sample code you can use -
public static void writeTestResultToXLSX(File scenarioFile, String testCaseID, int cellNo, resultEnum rEnum) {
FileInputStream fis;
try {
fis = new FileInputStream(scenarioFile);
XSSFWorkbook workbook = (XSSFWorkbook) WorkbookFactory.create(fis);
XSSFSheet sheet = workbook.getSheetAt(0);
int rowNum = Integer.parseInt(testCaseID);
Row row = sheet.getRow(rowNum);
row.createCell(cellNo).setCellValue(rEnum.toString());
fis.close();
FileOutputStream fos = new FileOutputStream(scenarioFile);
workbook.write(fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (EncryptedDocumentException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
In above code, scenarioFile is the name of the excel file you want to read, cellNo is the cellNo where you want to write the result back, rEnum is Enum that has predefined value - PASS and FAIL.
In below way, you can call this function -
ApachePOIMethods.writeTestResultToXLSX(scenarioFile, testCaseID, XLSXresultCell, resultEnum.FAIL);
One thing to make sure is not to hard code anything, the complete code is big so cannot be copy-pasted here so as to keep answer short, you can find complete script here.