When doing unittest you have two components: The unittest itself and the code under test (cut).
Your example looks like as if you try to build a unittest by simply adding the @Test
annotation to the tested code. This does not work.
As a start you should create a class containing you production code (the cut) and another class with the same name appended with Test
:
class ProductionCode {
// something to test
}
and
class ProductionCodeTest {
// the tests for the production code
}
The responsibility of the *Test
class is to set up a test environment for the cut. In your case this involves to replace any dependencies (as System.in
or the Scanner
object wrapping it and System.out
) with test doubles. The best way to do this it to use a mocking framework like Mockito
:
@ExtendWith(MockitoExtension.class)
class ProductionCodeTest {
@Mock
private Scanner input;
@Mock
private PrintWriter output;
private ProductionCode cut;
@BeforeEach
void setup(){
cut = new ProductionCode(input,output);
}
}
But this raises the problem that you need a possibility to replace the real dependency in your cut. This is done preferably via *constructor injection:
class ProductionCode {
private final Scanner scanner;
private final PrintWriter output;
ProductionCode(Scanner scanner, PrintWriter output){
this.scanner = scanner;
this.output = output;
}
void main(){
int judge = 1;
while (judge == 1)
{
int n = scanner.nextInt();
output.println("输入的数为:" + n);
if (n == 0)
judge = 0;
}
}
}
Now you can verify the expected behavior of your cut which is the return value (which you don't have) and/or communication with its dependencies, which is the methods called and parameters passed:
@ExtendWith(MockitoExtension.class)
class ProductionCodeTest {
@Mock
private Scanner input;
@Mock
private PrintWriter output;
private ProductionCode cut;
@BeforeEach
void setup(){
cut = new ProductionCode(input,output);
}
@Test(name="returns when user entered '0'")
void test(){
// arrange / given
Mockito.when(input.nextInt()).thenReturn(1,2,3,4,5,0);
// act / when
cut.main();
// assert / then
Mockito.verify(output, Mockito.times(6))
.println(Mockito.anyString());
}
}
Conclusion
Unittesting is more that just writing a random annotation to some code written. Your example became complex very quickly because you choose a rather hard to test scenario to start. I'd suggest a pure function like a method that adds two numbers and returns the result as a better starting point and deal with the dependency stuff later.