I have a task to test a console application. I can access one method, but would also like to check that the string formatting is working correctly.
As this method does not return a string, but rather prints to the console, is there a way I can intercept the list printed line?
Does it even make sense to test this sort of thing?
Here is a sample how to catch output to the System.out:
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
System.setOut(new java.io.PrintStream(out));
System.out.println("Test output");
System.err.println("Out was: " + out.toString());
You can use System.setOut() to redirect the System.out.println writes to a PrintStream(OutputStream). Then you can write that OutputStream to a String and test it.
The way for testing this its make a good design with a "output" abstraction instead of print directly to "system.out". For example:
interface Output {
void print(String data);
}
Then you inject this dependency into the class that needs to send information to the output:
class MyProgram {
private Output out;
public MyProgram(Output output) {
this.out = output;
}
public doSomething() {
// do something
out.print("i do something!);
}
}
Then you can test easily with a mock (with mockito for example):
public void test_my_program() {
Output mockOutput = mock(Output.class);
MyProgram myProgram = new MyProgram(mockOutput);
myProgram.doSomething();
verity(mockOutput).print("do something!");
}
I don't verify the code but its more or less correct and i expect enough for you to get the idea. Always its the same, testing its not difficult, the difficult thing its design good testable code, here we are only using abstraction and dependency injection, two basic principles of OO.
The real advantage of this code its that now its not tied to "System.out", you can use this class in a web application for example if you want. For example making and output implementation that talks to the web client via websocket. This is another OO principle, your class is now "Open-Close", you can add functionality (websocket crazy example :P) without modify your actual code.
Related
I have an existing Java class that writes to a file.
public final class WriteToFile{
private Writer file_writer;
private static final String encoding_format = "UTF8";
private FileWrite(final File fpath) throws IOException {
this.file_writer = new OutputStreamWriter(new FileOutputStream(fpath), encoding_format);
}
#Override
public void fileWrite(final String msg) {
try {
this.file_writer.write(msg);
this.file_writer.write("\n");
this.file_writer.flush();
this.file_writer.close();
} catch (IOException e) {
log.error("File write failed", e);
}
}
}
In order to unit test this, I learnt that creating a file mock using a Mocking framework is not a good practice . What do I test here? The only way of testing this is to probably do the file write again, and check if the expected contents and actual contents are the same. In that case, doing it the JUnit way would be as mentioned in this post How to test write to file in Java?. However, I am not going to rewrite the file writing code, to include interface wrappers. How do I go about with this?
#Test public void testfileWrite() {
String msg = "somemessage";
String fpath = "path/to/file";
Writer file_writer = new OutputStreamWriter(new FileOutputStream(fpath), "UTF8");
file_writer.write(msg);
assertEquals("somemessage", file_writer.toString());
}
Is this all that needs to be tested?
The point of this class is to write a file. It does nothing else (and that is a good thing). So don't bother with a mockist unit test, all it shows is that you can write a ton of mock code. Instead write a Integration Test.
Use the JUnit rule TemporaryFolder to create and destroy a folder to put your test file in, then verify the file has what you want in it at the end of the test. The only time you should consider mocking for this kind of test is if the exceptional case does something funky. Then you can either do some evil black magic involving Powermock or pass in some form of "File Stream factory". Or ask yourself if that is really such a great place for complex logic that needs testing, and then move it.
When testing classes that make use of WriteToFile, mock or stub WriteToFile.
When it comes to write unit tests that must check generated files, I always prepare myself a repository of cases: For each case, an input file (if necessary), and and a set of expected output files.
I write one test method for each case, where I call the business logic, which will generate one (or some) file into the working directory, and I eventually check if the generated file is equal to the proper expected file.
I prepare the expected files manually and check them in into the Source Control System, so that they belong to each released version. If, in future, the business logic must change its behaviour, then it is required that the expected file be changed accordingly, and that both the code and the file be checked in and tagged together in the same release.
That is the easiest and safest way I found for checking generated files.
Use Powermockito to mock the call to the constructor of FileOutputStream and OutputStreamWriter as in: http://benkiefer.com/blog/2013/04/23/powermockito-constructor-mocking/
Then verify that file_writer methods write(String) and flush() have been invoked twice and once, respectively; and at the end close().
I am not sure if it is possible but if so how do I do it? I have a project which contains another 2 projects as dependencies. The parent project is only used for testing purposes (client server app). When I am testing I have a difficulty reading through my testing output because of the large amount of output the client and the server projects have. I am trying to find a way hide from the console all the output(printf()) of my sub-projects so that I can only see my testing output. Is there a way to do so?
For testing I am using JUnit.
Thanks
You should use Java Logger API (or Log4J) instead of using System.out.print directly, sou you could disable specific loggers during executions of your tests.
If you can't change legacy code to use Logger API, there are two options:
Option 1:
Create a PrintStream decorator class like this pseudo-code:
public class FilteredPrintStream extends PrintStream {
private final PrintStream stream;
...
#Override
public void print(String str) {
if (notCalledBySubproject()) {
stream.print(str);
}
}
// override other methods too
}
Then you set default output: System.setOut(new FilteredPrintStream(System.out));
To find method caller (to create notCalledBySubproject method), see How do I find the caller of a method using stacktrace or reflection?
Option 2:
Use Logger API in your test code, so you can redirect your output to a file, for example, then you ignore console output and see the file generated by your tests.
It is not a perfect solution nor good coding practice but you could add a class like this
public class SystemOutput
{
public static final boolean DO_PRINT = true;
public void printf(String format, Object... args)
{
if(DO_PRINT)
System.printf(format, args);
}
}
and use Find and Replace once to replace "System.out.printf" with "SystemOutput.printf" in every class needed. Because both methods have the same declaraction only this has to be changed. When you want to block the output you can just set DO_PRINT to false.
Eclipse for example provides a search tool which can find and replace a certain string in every .java file in a project. (Strg + H under the File Search tab)
of course it is also possible to call System.setOut() with your own subclass of PrintStream, that overrides the printf() method to only print when a certain boolean value is true.
why do you need console to run unit tests? ignore it. if your tests passes you got 0 status code or green bar (IDE or jenkins). any error stack trace you can find in e.g. maven log tests results. just ignore the std output
another thing: using console in your application is usually bad idea - avoid it. use logging framework instead (it will let you control the destination and level of logging). use your IDE and refactor - replace all calls to printf with log.debug or with you own wrapper. if your IDE doesnt support it then use some regex and try replace-all
if you want to get rid of all the output you can redirect stdout to /dev/null or change output stream in java. but it's not a proper solution
I want to test that a specific method produces the expected result, but to do that I need to manipulate the input in the test as well.
class ToTest {
public String produceResponse(String input) {
// ....
encryptedIds = encryptIds(input)
output = doStuff(input, encryptedIds)
}
public encryptIds(input) {
....
}
}
In my test I need to check that produceResponse actually produces the expected response.
in order to do that I have to encrypt the ids in the input.
My question is: should I rewrite encryptIds in the test (so that I would have more controller on the result) or should I call encryptIds from the class itself.
Is there a better approach to solve this? I don't like that in my test I know what happens in the specific flow.
If I understand correctly, you would like to test produceResponse() with known encryptedIds as input.
You could do that without refactoring the code, but it would probably be a good idea to refactor it, so that's what I'm going to explain:
class ToTest {
private IdEncryptor encryptor;
public ToTest(IdEncryptor encryptor) {
this.encryptor = encryptor;
}
public String produceResponse(String input) {
String[] encryptedIds = encryptor.encryptIds(input);
return doStuff(input, encryptedIds);
}
}
Now you can unit-test IdEncryptor to test that it produces correct encrypted IDs based on a String input.
And to test the ToTest class, you can mock the IdEncryptor so that whatever the input it receives, it produces the encryptedIds you desire. For example with mockito:
IdEncryptor mockEncryptor = mock(IdEncryptor.class);
when(mockEncryptor.encryptIds(any(String.class)).thenReturn(new String[] {"a", "b"});
ToTest toTest = new ToTest(mockEncryptor);
String response = toTest.produceResponse("input");
// expect that the response is what you expect given "a", "b" as input of doStuff()
Never copy any production code into the unit test as it will get outdated at some point.
If both methods are public, they are part of the public API, so:
you should first unit test the correct behavior of the encryptIds(String) method
then unit test the produceResponse(String) method which will internally use the already tested encryptIds(String) method
If encryptIds(String) would not be part of the public API:
then it is internal implementation and helper method which is not unit testable
produceResponse(String) is then responsible for encryption as a side-effect:
you can still test it if you mark it package private (no modifier)
you can also change the implementation of the encryptIds(String) only for testing purposes
Is encrypting id's something that is integral to your system or not? As it stands this class takes some input and produces some output and as far as your test is concerned this is what's important, no more, no less.
What is the impact of not performing the encryption? If your doStuff method will just fail if it doesn't happen then it is an internal detail to your class-under-test and I wouldn't have the tests care about it at all. If it's a step that absolutely must be performed then I would refactor the code to verify that it absolutely has happened, maybe using a mock as #jb-nizet answered.
As for the general case of duplicating production code in tests, as #Crazyjavahacking stated you should not do this, but I have no issue with using production code from a test- maybe not at a unit level but definitely the higher up the system I go, e.g. when testing writing to a DB I will use the reading code to verify it's happened correctly, but will also have independent tests to verify the reading path as well
I have started reading the Spring in Action book.
I have no knowledge of JUnit which I think my doubt is about.
There is a code fragment where the author refers to and says that it is difficult to test:
package com.springinaction.knights;
public classDamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
quest = new RescueDamselQuest();
}
public voidembarkOnQuest() throwsQuestException {
quest.embark();
}
}
The author says that:
It’d be terribly difficult to write a unit test for DamselRescuingKnight. In such a test, you’d like to be able to assert that the quest’s embark() method is called when the knight’s embarkOnQuest() is called. But there’s no clear way to accomplish that here. Unfortunately, DamselRescuingKnight will remain untested.
What does the author mean by this?
Why is the code difficult to test here?
My initial thought is that it is difficult to test because the "RescureDamselQuest" object is initialized in the constructor. This makes it difficult to for example insert a mock object. A mock object would help you test that the embark() method is called on the "RescueDamselQuest" object.
A better way to solve this can be to either include a parameter in the constructor (usually I prefer this method):
public DamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
Or add a setter:
public void setDamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
A common example I give is consider that you want to open a file, parse it, and get a data class out. Most will do something like:
Data openAndParse(String filename) {
...openFile
...parse
}
By doing it this way, the file open methodology and parse is highly coupled and difficult to test. If you have a problem in open and parse is it with the parse or the open?
By writing JUnit test, you are forced, for simplicity sake, to do something like...
BufferedReader openFile(String filename) {
...open file and return reader
}
Data parse(BufferedReader input) {
...parse and return data
}
JUnit leads us to a more cohesive solution. We write JUnit test simply by creating a string, constructing a StringReader, and then a BufferedReader. Well guess what? Very similarly we can now use parse to accept input from a variety of sources not just the file.
It's difficult to test because the quest implementation cannot be swapped out. Without byte code modification there's no trivial way to see if embark is called.
If you could set the quest implementation in a constructor or setter you could pass in an implementation that can spy on the call to embark.
One need to increase accessibility of fields and method of class to test. For example if one is testing a method which is package-private (default) then test cases which are generally in different package will not able to test this method. Therefore it is advised to to change in accessibility of fields to test the method. DamselRescuingKnight class can be tested which is not using DI by modifying the accessibility of RescueDamselQuest field from private to default. Then writing test case using mockito. Here is code for test case
#Test
public void knightShouldEmbarkOnQuest() throws QuestException {
DamselRescuingKnight knight = new DamselRescuingKnight();
RescueDamselQuest quest = mock(RescueDamselQuest.class);
knight.quest = quest;
knight.embarkOnQuest();
verify(quest, times(1)).embark();
}
And line which was changed in DamselRescuingKnight class to remove private accessibility
RescueDamselQuest quest;
For debugging purposes I need to keep track of a Class attributes changes.
For example consider the following class:
class Test {
int myInt;
String myString;
...
public void setMyInt(int a) ...
public void setMyString(String s) ...
public printDebugLog();
}
void main() {
Test t = new Test();
t.setMyInt(5);
t.setMyString("Hello");
t.printDebugLog();
}
I want to output to be something like:
myInt => 5
myString => Hello
The easy solution is to create logs instantly. i.e. adding a Log function as follow:
void Log(String s) {
System.out.println(s);
}
and then code the set functions like below:
void setMyString(String s) {
myString = s;
Log("myString => " + s);
}
this requires all the set functions to be written variously and I wonder if there are any better solution for such matter. For example it might be easier (if possible) to create a SetValue function which accepts two variables and set the first attribute to the value of the second object. or something like this.
Any idea?
To do this you should wrap your class with orthogonal code that performs logging.
Since your class does not implement interface you cannot use dynamic proxy, so you have to use one of solutions that use byte code engineering.
The strongest solution I know is AspectJ. But probably you even do not need it. You can use Javassist or CGLIb - the byte code engineering libraries that allow creating proxies that wrap classes, so you can add code that performs logging.
You can use AOP to intercept the setter methods and log when they are called. A quick google should give you a few examples.
If you debug via JPDA,
you can create a Breakpoint
on a field you like to watch.