1

I'm trying to test this segment of code using Mockito

if (writeToDisk(filename, byteArray)){ return "URI1" } else { return "URI2" } 

Since that writeToDisk is intended to be run on a unix server, so using a buffered+fileWriter it writes to "/tmp/upload". The issue is that i'm writing unit tests on a windows machine, and writeToDisk always returns false, because java cannot find "/tmp/upload on windows.

Is there any way I can mock the result of writeToDisk, a pacakge private method?

This is what writeToDisk does:

boolean writeToDisk(String filename, byte[] data){ boolean writeSuccessful = false; try (BufferedWriter writer = new BufferedWriter(new FileWriter("/tmp/upload"+ filename"))){ for (byte current : data){ out.write(current); } writeSuccessful =true; } catch (IOException e) { LOG.debug(e); } return writeSuccessful; } 
2
  • 3
    Extract out into own service that can be mocked when testing. Avoid tight coupling to implementation concerns Commented Jul 23, 2018 at 20:12
  • 1
    You could use a spy. This lets you have an object of a particular class, where one or more method's implementations have been replaced with different implementations. So you can change the implementation of writeToDisk and test the spy. Commented Jul 23, 2018 at 20:13

2 Answers 2

3

The real answer is here:

try (BufferedWriter writer = new BufferedWriter(new FileWriter("/tmp/upload"+ filename"))){ 

You are hardcoding a ton of things here, like that (OS specific) path, and the exact kind of writer. That makes this client (that only wants to write stuff somewhere) extremely dependent on all these aspects. Thus it becomes really hard to test!

You could easily turn all these aspects into some sort of service, where you only go:

try (Writer writer = service.getWriterFor(filename)) 

(or something alike, just giving some inspiration here)

That service you could easily mock, directly enabling you to unit that this code as well.

It would be just a very small abstraction (probably some @FunctionalInterface, that can be initialised in the production with a nice lambda or method reference).

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

3 Comments

I would abstract out the whole boolean writeToDisk method. Nice and clean separation of concerns.
@Nkosi Who tells you that this isn't already "abstracted out" and a service on its own?! That is the point: this code is still doing too many things, and needs to be further dissected. It is already providing a service (writing a file with logging and stuff), but it should delegate said aspects onto some other service.
Agreed. I was referring to the first snippet in the OP. Yes the method in question also needs some refactoring as well but in relation to the segment to be tested that is what I was referring to.
0

One of the advantages of unit testing is that it forces you to improve on your design.

So yes, as suggested by other people, you need to add dependency injection.

I would suggest that you create a class named FileCreator and give it a method boolean createFile(byte[]) and maybe if you need it String getCreatedFileName().

As an added advantage, looks like the file name needs not be part of the call and may be converted into a property of the new class.

Another potential advantage: if your code becomes mutltithreaded, you can have a creator-per-thread, all writing to different files.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.