1

I'm quite new to java programming, but I'll try to use the correct terms and avoid misunderstandings as much as possible.

I've found some answers to topics quite similar to my problem but or I just cannot see how they really fit to my problem, or maybe they really just don't fit. Some of them use mocked objects but I'm not sure it is the right option in my case.

General description

I need to have an array of objects which information is loaded from a random accessed binary files. The first bytes of the binary files are the header of the files which define how the data is stored in the files, basically says the length of some fields which help to compute the position of desired data in the files.

So now I want to test the method that will be called to load the desired data, which is specified by UnitListElement object, to the Unit object. For this I only focus on a single reading of a binary file.

More detailed view

I have a java class called Unit with some attributes, let's say a,*b* and c. The value for this attributes is loaded with a method call getDataFromBinFile:

public class Unit{
    public double[] a;
    public double[] b;
    public double[] c;

getDataFromBinFile(UnitListElement element){
    <here loads the data from the binary file with random access>
}
}

The method for loading the data from the binary file, opens the binary file and access to the desired data in the binary file. The desired data to be read is specified in a UnitListElement object:

public class UnitListElement{
    public String pathOfFile;
    public int beginToReadAt;  // info related to where the desired data begins
    public int finishReading;  // info related to where the desired data ends
} 

The attributes beginToReadAt and finishReading time references which are used, along with the binary file's header, to compute the first and last byte positions to read from the binary file.

So what I need to do is a test where I call the method getDataFromBinFile(unitListEl) and test whether the info returned is correct or not.

options for solutions

1st option

In some posts with similar problems propose to use mock objects. I've tried to find documentation about mocking objects but I haven't found any easy beginners guide. So although not understanding mock objects very much, my impression is that the do not fit into this case since what I want to test is the reading of the binary file, not just the interaction with other objects.

2nd option

Another option is to create the binary file for the test inside the test with a helper method, f.i. with a @BeforeClass, and run the test with this temporary file and then delete it with a @AfterClass method.

Question

What do you think is the best practice considering a TDD approach? Do mock objects really fit in this case? If they do, is there any documentation with basic examples for total beginners?

or on the other hand, the creation of the file is more suitable for testing reading methods?

Thanks

Lots of thanks in advance.

4 Answers 4

1

Mocking can be applied to your case, but it is in fact not strictly necessary here. All you need is decouple the actual data processing logic in getDataFromBinFile from the code reading the bytes from files.

You can achieve this in (at least) two ways:

  • With mocks: hide the file reading code behind an interface method which takes a UnitListElement and returns a byte array, then use this in getDataFromBinFile. Then you can mock this interface in your tests with a mock reader which just returns some predefined bytes without accessing any files. (Alternatively, you can move the file reading logic into UnitListElement itself, as for now it seems to be a POD class.)
  • Without mocks: change the signature of getDataFromBinFile to take a byte array parameter instead of a UnitListElement. In your real production code, you can read the data from the file position described by the UnitListElement, then pass it to getDataFromBinFile. In your unit tests, you can just pass any binary data to it directly. (Note that in this case, it makes sense to rename your method to something like getDataFromBytes.)

For mocking, I have been using EasyMock so far. I find its documentation fairly easy to understand, hope that helps.

Sign up to request clarification or add additional context in comments.

7 Comments

First point for me really summarizes mocking and illustrates it with nice simplicity :) .
@theme, 1) by interface method in general, I simply mean a public method of a class or interface. 2) IMO the simplest would be to return only the desired portion of the file data, which getDataFromBinFile needs to process.
I have a couple of questions, as I'm also new to java. - By interface method,do you mean a java interface (class X implements Y)? Or just a method that interacts with UnitListElement and file? - That interface method, would put all bin file's data in the byte array to be used by getDataFromBinFile?. If so, the method getDataFromBinFile would also need the two attributes from UnitListElement to compute the position of the desired bytes. For production code Isn't it less optimal to load all the bin file's data to a byte array instead of reading just the required info?
ok ok I got the point, I'll think about it and try to fit it in the real code. Since some of the Unit's attributes are objects also, thus having a cascade of objects to be filled with data, I'll need some time to not mess it up. Sorry also for the multiple modifications of the previous comment but I couldn't figure out hot to put a bullet list with <ul> tag.
@theme, no probs :-) AFAIK you can't have a bulleted list in a comment :-(
|
0

I don't have much experience in TDD. Is not required to use mocking when you are testing read/write to a file, best option is to have a test version of file on which you test will run. Mocking is meant to be used when you can not easily create a testable object for your use case, i.e if you are testing interaction with a server for example.

Comments

0

I don't prefer creating the test binary files , as any change in the format of file being read means changing the test files as well ( and thus the tests ) .

Since you are following a TDD approach , you must be having the tests written out for the "UnitListElement" class , hence for the situation mocking seems to be a better solution . Your objective is to test the "getDataFromBinFile" method and not the "UnitListElement" class methods (currently) hence you can mock "UnitListElement" class ( or interface inherited by it and passed to getDataFromBinFile method ) . Mocking "UnitListElement" means you can return predefined or any specific return values to any method calls in the class whenever it is accessed in "getDataFromBinFile" method . Finally you could use the returned values from your mock in the "getDataFromBinFile" method and assert for the return value of the method after your business logic is performed . I haven't used too many mocking frameworks , however most often i have been using EasyMock framework .For a start you can get a basic example of EasyMock over here

Comments

0

Just make a test binary file.

This process is reading a file. So there is no reason to worry about the file system. the file will always be deterministic (if you altered the file durning reading that would be an other story)

if you want to do a test with the objects after you've read them in, I would suggest just creating them in your test (unless this is very hard to do, like a sound file)

Also, I would suggest the abstraction of a stream instead of a file, but I would STILL test this with a test file. btw: make sure the test file is small, it's a test after all.

Some people might argue "test aren't suppose to hit the file system" but where do you think the .class files are loaded from?

Also, I would get the stream via the java classLoader

this.getClass().getResourceAsStream("yourfile.name");

happy testing!

Llewellyn Falco

http://www.approvaltests.com

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.