Reputation: 131
I want to do a JUnit test on the ForecastDisplay class below that has no return value. The way this class works is that the currentPressure=29.92f gets replaced by a new pressure assigned in the tester class. The display method compares the new and old pressures and prints the appropriate message to the console. As this is a void method, I don't know how to test it.
For example: if I assign a new currentPressure of 35 in the JUnit test, then the first message will print because 35>29.92. If anyone could suggest how to test this I would appreciate it because so far I can't do this without changing the display method to return a value, which is cheating as I shouldn't have to adapt the code to pass a JUnit test. Thanks
public class ForecastDisplay implements Observer, DisplayElement {
private float currentPressure = 29.92f;
private float lastPressure;
private WeatherData weatherData;
public ForecastDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temp, float humidity, float pressure) {
lastPressure = currentPressure;
currentPressure = pressure;
display();
}
public void display() {
System.out.print("Forecast Display: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
} else if (currentPressure == lastPressure) {
System.out.println("More of the same");
} else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
}
}
Upvotes: 1
Views: 7684
Reputation: 866
Even if you can't refactor display add a getter for current pressure and use it in your tests to determine that it is set correctly.
Upvotes: 0
Reputation: 16060
If you can't refactor the display()
method as others have suggested (and I agree) as the best solution, you could intercept System.out
and make your asserts on that:
@Test
public void testDisplay()
{
final ByteArrayOutputStream out = new ByteArrayOutputStream( 256 );
PrintStream ps = new PrintStream( out );
System.setOut( ps );
Forecast f = new Forecast(...);
f.update( ... );
assertThat( "Expected whatever" , out.toString() , equalTo( "..." ) );
}
Cheers,
Upvotes: 2
Reputation: 473
In Java you can do a System.setOut(yourOutStream)
use that and do a @Before and @After to clean up by System.setOut(null)
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
@Before
public void redirectOut() {
System.setOut(new PrintStream(out));
}
@After
public void cleanUpOut() {
System.setOut(null);
}
and then you can test it like:
@Test
public void shouldUpdatePresure() {
update(101.5, 80.0, 25.2);
assertEquals("somevaluehere", out.toString());
}
Upvotes: 2
Reputation: 248
I would suggest you create gettters and setters for your private methods (if you're using Eclipse: right click your class and select source, create getters and setters and click "select all"). Then, you could just use these methods to see if your private variables have changed.
@Test
public void testUpdate1() {
//create a new instance of ForecastDisplay, for example fcd
...
fcd.update(29, 45, 35);
assertEquals(fcd.getCurrentPressure, 35, 0);
}
Upvotes: 0
Reputation: 6450
This could be a good example of a class to refactor - if possible, you may not have the scope to do so - to make it more testable. E.g. if your method returned a String you could test it better. So one option could be to create two methods:
Or, have displayForecast() call generateDisplayString() itself. There are a few models you could use that wil make your class more testable.
Upvotes: 1
Reputation: 107317
As it stands, you would need a tool like PowerMock
to mock System.out
in order to determine what the method tried to print. How about breaking up the concerns of working out the message (which needs to be tested) and the concern of display.
public String determineMessage() {
String msg = "Forecast Display: ";
if (currentPressure > lastPressure) {
msg += "Improving weather on the way!";
} else if (currentPressure == lastPressure) {
msg += "More of the same";
} else if (currentPressure < lastPressure) {
msg += "Watch out for cooler, rainy weather";
return msg;
}
public void display() {
System.out.println(determineMessage());
}
This way unit testing can be done by setting various pressures on the class and asserting that the message is determined correctly.
Upvotes: 2