This was a source of a little frustration to me... because I like to start off the most sophisticated of GUI apps with a console handler.
The language I'm using here is Groovy, which is a sort of marvellous extension of Java, and which can be sort of mixed in with plain old Java.
class ConsoleHandler {
def loopCount = 0
def maxLoopCount = 100000
void loop() {
while( ! endConditionMet() ){
// ... do something
}
}
boolean endConditionMet() {
loopCount++
loopCount > maxLoopCount // NB no "return" needed!
}
static void main( args ) {
new ConsoleHandler().loop()
}
}
... in a testing class (also in Groovy) you can then go
import org.junit.contrib.java.lang.system.SystemOutRule
import org.junit.contrib.java.lang.system.
TextFromStandardInputStream.emptyStandardInputStream
import static org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import static org.mockito.Mockito.*
class XXTests {
@Rule
public SystemOutRule systemOutRule = new SystemOutRule().enableLog()
@Rule
public TextFromStandardInputStream systemInMock = emptyStandardInputStream()
ConsoleHandler spyConsoleHandler = spy(new ConsoleHandler())
@Test
void readInShouldFollowedByAnother() {
spyConsoleHandler.setMaxLoopCount 10
systemInMock.provideLines( 'blah', 'boggle')
spyConsoleHandler.loop()
assertThat( systemOutRule.getLog() ).containsIgnoringCase( 'blah' )
assertThat( systemOutRule.getLog() ).containsIgnoringCase( 'boggle' )
The beautiful thing that's happening here is that simply by declaring maxLoopCount
the language automatically creates two methods: getMaxLoopCount
and setMaxLoopCount
(and you don't even have to bother with brackets).
Of course the next test would be "loop must exit if a user enters Q" or whatever... but the point about TDD is that you want this to FAIL initially!
The above can be replicated using plain old Java, if you must: you have to create your own setXXX
method of course.