I have a following save method, but I dont know how to verify this method. How can i verify it in JUnit ??
public static void save(Spiel spielen,File file ) {
try(ObjectOutputStream out= new ObjectOutputStream(new FileOutputStream(file))) {
out.writeObject(spielen);
System.out.println("Speichern Erfolgreich");
System.out.println();
}
catch (Exception e) {
System.out.println("Fehler beim Speichern");
System.out.println();
}
}
One simple solution: don't pass in a file object. But instead a factory that creates an OutputStream for you.
At runtime, this could be a FileOutputStream. But for testing, you could pass a different factory that creates, say a ByteArrayOutputStream. Then your code writes to memory without knowing it.
And then you could write another test that reads back these bytes.
You can store the reference, expected output file on the disk, and then compare the tested output against that. There are many ways to do that comparison, including some JUnit Addons (its FileAssert in particular), or just read both files into byte arrays and assert that they equal.
Many other utilities exist, some listed on this answer: File comparator utilities
Related
I am creating a JUnitTest test that compares a file that is created with a benchmark file, present in the resources folder in the src folder in Eclipse.
Code
public class CompareFileTest
{
private static final String TEST_FILENAME = "/resources/CompareFile_Test_Output.xls";
#Test
public void testCompare()
{
InputStream outputFileInputStream = null;
BufferedInputStream bufferedInputStream = null;
File excelOne = new File(StandingsCreationHelper.directoryPath + "CompareFile_Test_Input1.xls");
File excelTwo = new File(StandingsCreationHelper.directoryPath + "CompareFile_Test_Input1.xls");
File excelThree = new File(StandingsCreationHelper.directoryPath + "CompareFile_Test_Output.xls");
CompareFile compareFile = new CompareFile(excelOne, excelTwo, excelThree);
// The result of the comparison is stored in the excelThree file
compareFile.compare();
try
{
outputFileInputStream = new FileInputStream(excelThree);
bufferedInputStream = new BufferedInputStream(outputFileInputStream);
assertTrue(IOUtils.contentEquals(CompareFileTest.class.getResourceAsStream(TEST_FILENAME), bufferedInputStream));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
However, I get an Assertion Error message, without any details. Since I just created the benchmark file from the compare file operation, both files should be identical.
Thanks in advance!
EDIT: After slim's comments, I used a file diff tool and found that both files are different, although, since they are copies, I am not sure how that happened. Maybe there is a timestamp or something?
IOUtils.contentEquals() does not claim to give you any more information than a boolean "matches or does not match", so you cannot hope to get extra information from that.
If your aim is just to get to the bottom of why these two files are different, you might step away from Java and use other tools to compare the files. For example https://superuser.com/questions/125376/how-do-i-compare-binary-files-in-linux
If your aim is for your jUnit tests to give you more information when the files do not match (for example, the exception could say Expected files to match, but byte 5678 differs [0xAE] vs [0xAF]), you will need to use something other than IOUtils.contentEquals() -- by rolling your own, or by hunting for something appropriate in Comparing text files w/ Junit
I had a similar issue.
I was using JUNIT assertion library Assertions and got the memory address being compared rather than the actual file it seemed.
Instead of comparing the InputStream objects I converted them to byte arrays and compared those. Not an absolute specials, but I dare to claim that if the byte array is identical, then the underlying InputStream and its file have a large chance of being equal.
like this:
Assertions.assertEquals(
this.getClass().getResourceAsStream("some_image_or_other_file.ext").readAllBytes(),
someObject.getSomeObjectInputStream().readAllBytes());
Not sure that this will scale though for larger files. Certainly not OK for complex diffs, but it does the trick for an assertion.
I am training TDD approach, but I have a problem. How to test IO operations ? I used junit so far, but I read that it shouldn't be used to test with external sources ( databases, files ...), so what will be better ? Sorry for my bad English
You can't test the internal working of those external sources, but you can check the results.
For example, writing to a file:
Start test
Store data you want to write in a variable
Write data to file
Read file
Check if data is the same as the one you stored
End test
Testing is about verifying end results, so it's not necessarily a bad thing you "lose" sight of a part of the process. Generally you can assume external sources (libraries, IO..) are well tested.
Change your API to be passed InputStream and/or OutputStream and have your jUnit code pass ByteArrayInputStream and ByteArrayOutputStream, which you can easily set up/read from.
Of course your production code would need to change to, but you can often achieve this through a simple refactoring; leaving the API as-is but having the public methods call the refactored method, for example:
Change
public void read(File file) {
// do something with contents of file
}
To
public void read(File file) {
read(new FileInputStream(file));
}
// test this method
public void read(InputStream inputStream) {
// do something with contents of inputStream
}
Okay, so my issue is that i have alot of programs that i am using in java that use the exact same array of objects but i dont want to keep recreating this array every time that i write a new program. Is there a way to save an array of objects for use in other java programs. if so how?
If you are a beginner you should serialize the array of objects into a file. The convention is to name your serialized file name-of-file.ser
try
{
FileOutputStream fileOut = new FileOutputStream("card.ser");//creates a card serial file in output stream
ObjectOutputStream out = new ObjectOutputStream(fileOut);//routs an object into the output stream.
out.writeObject(array);// we designate our array of cards to be routed
out.close();// closes the data paths
fileOut.close();// closes the data paths
}catch(IOException i)//exception stuff
{
i.printStackTrace();
}
to deserialze it use this:
try// If this doesnt work throw an exception
{
FileInputStream fileIn = new FileInputStream(name+".ser");// Read serial file.
ObjectInputStream in = new ObjectInputStream(fileIn);// input the read file.
object = (Object) in.readObject();// allocate it to the object file already instanciated.
in.close();//closes the input stream.
fileIn.close();//closes the file data stream.
}catch(IOException i)//exception stuff
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)//more exception stuff
{
System.out.println("Error");
c.printStackTrace();
return;
}
To serialize an object, create an ObjectOutputStream and call writeObject.
// Write to disk with FileOutputStream
FileOutputStream f_out = new
FileOutputStream("myobject.data");
// Write object with ObjectOutputStream
ObjectOutputStream obj_out = new
ObjectOutputStream (f_out);
// Write object out to disk
obj_out.writeObject ( myArray );
Reference
You can serialize many kinds of objects. Yes, an array is a object too (#see Array class). If you don't wan't the limitations of Arrays, you could use one of the Container classes (eg LinkedList) too. The serialization works the same way.
Write a class that manages this array. Put this class, along with classes it depends on, in its own JAR. Re-use JAR across multiple programs.
If you use Eclipse, you can do that by creating a new Java project (let's call it project OM - from Object Model) and putting the Foo and FooManager classes there. Then in each project you want to reuse the objects, in the Build Properties of the project add the OM project to the class path and to the exports tab. That's it.
I've made two apps designed to run concurrently (I do not want to combine them), and one reads from a certain file and the other writes to it. When one or the other are running no errors, however if they are both running a get an access is denied error.
Relevant code of the first:
class MakeImage implements Runnable {
#Override
public void run() {
File file = new File("C:/Users/jeremy/Desktop/New folder (3)/test.png");
while (true) {
try{
//make image
if(image!=null)
{
file.createNewFile();
ImageIO.write(image, "png", file);
hello.repaint();}}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Relevant code of the second:
BufferedImage image = null;
try {
// Read from a file
image = ImageIO.read(new File("C:/Users/jeremy/Desktop/New folder (3)/test.png"));
}
catch(Exception e){
e.printStackTrace();
}
if(image!=null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( image, "png", baos );
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
returns=Base64.encodeBase64String(imageInByte);
}
I looked at this: Java: how to handle two process trying to modify the same file, but that is when both are writting to the file where here only one is. I tried the retry later method as suggested in the former's answer without any luck. Any help would be greatly appreciated.
Unless you use OS level file locking of some sort and check for the locks you're not going to be able to reliably do this very easily. A fairly reliable way to manage this would be to use another file in the directory as a semaphore, "touch" it when you're writing or reading and remove it when you're done. Check for the existence of the semaphore before accessing the file. Otherwise you will need to use a database of some sort to store the file lock (guaranteed consistency) and check for it there.
That said, you really should just combine this into 1 program.
Try RandomAccessFile.
This is a useful but very dangerous feature. It goes like this "if you create different instances of RandomAccessFile for a same file you can concurrently write to the different parts of the file."
You can create multiple threads pointing to different parts of the file using seek method and multiple threads can update the file at the same time. Seek allow you to move to any part of the file even if it doesn't exist (after EOF), hence you can move to any location in the newly created file and write bytes on that location. You can open multiple instances of the same file and seek to different locations and write to multiple locations at the same time.
Use synchronized on the method that modify the file.
Edited:
As per the Defination of a Thread safe class, its this way.. " A class is said to be thread safe, which it works correctly in the presence of the underlying OS interleaving and scheduling with NO means of synchronization mechanism from the client side".
I believe there is a File which is to be accessed on to a different machine, so there must be some client-server mechanism, if its there.. then Let the Server side have the synchronization mechanism, and then it doesnt matters how many client access it...
If not, synchronized is more than enough........
I'm trying to serialize java objects but i keep getting a list of errors. my program accepts multiple values and creates an instance of a class with them. the created object then gets stored in a StorageSystem class... it looks something like this
aCD = new CD(title, artist, playTime, numOfTracks);
store.addItem(aCD);
Then in the storage system i add the stored object to an arrayList... what i also want to do is add the object to a serialized file... my method for doing this is below... Am i going about this the wrong way. thanks...
public void addItem(Item hold) // adds object to the ArrayList
{
itemList.add(hold);
totalStored++;
FileOutputStream f_out;
try
{
FileOutputStream fout = new FileOutputStream("thequeue.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(hold);
oos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Code appears 'ok' . Theses are my observations :
Your class must implement the Serializable interface
FileOutputStream f_out; is never read
Instead of appending single object why don’t you put the entire ArrayList i.e (itemList) to the
object output stream
Catch 'IOException' first before trying 'Exception'
Code seems ok, except a double, unclear decaration (first f_out then fout declared and used).
Are you sure that classes that you want to serialize do implement the Serializable tag interface? In anycase I suggest you to write the whole ArrayList to the object output stream instead that trying to append single objects.
Well, it's not going to do what you want because every time you open the FileOutputStream it's going to overwrite the last file -- so you'll always have exactly one item in the file.
Also, your FileOutputStream is named f_out when you declare it outside the scope of the try, but you then create another one named fout inside that scope.
I'm not exactly sure what happens if you close the ObjectOutputStream instead of the FileOutputStream -- I think it should close the FileOutputStream but I'm not sure.