简体   繁体   English

如何对Java代码进行单元测试

[英]How to Unit test the java code

How to unit test this code using Junit 如何使用Junit对该代码进行单元测试

public class Diamond {

   public void DiamondShape(int num) {

       for(int ucount=num;ucount>0;ucount--) {
    //Loop to print blank space
        for(int count_sp=1;count_sp<ucount;count_sp++)
            System.out.printf(" ");
    //Loop to print *
        for(int count_ast=num;count_ast>=ucount;count_ast--)
            System.out.printf("* ");
        System.out.println();
       }
//Loop for lower half
  for(int lcount=1;lcount<num;lcount++) {
    //Loop to print blank space
    for(int count_sp=0;count_sp<lcount;count_sp++)
            System.out.printf(" ");
    //Loop to print *
        for(int count_ast=num-1;count_ast>=lcount;count_ast--)
            System.out.printf("* ");
    System.out.println();
    }
  } 
}

I am new at unit testing want some guidance on unit testing . 我是单元测试的新手,想要有关单元测试的一些指导。

Output when num=3 当num = 3时输出

   *
  * *
 * * *
  * *
   *

this is how the output should be, num indicates the star in center line 这就是输出的样子,num指示中心线中的星号

Instead of doing sysout you should refactor and make your method return the output. 而不是执行sysout,您应该重构并让您的方法返回输出。 You can then verify the output. 然后,您可以验证输出。

The other option is in your junit test create a Output stream and set it on the 另一个选项是在junit测试中创建一个Output流,并将其设置在

System.setOut(your output stream);

You can then verify the output stream. 然后,您可以验证输出流。

But this is not reliable as if your program executes some other code which also writing to the sysout then your output stream will have that data also. 但这并不可靠,因为如果您的程序执行了一些其他代码,这些代码也写入了sysout,那么您的输出流也将具有该数据。

In order to test a method it has to do one of these: 为了测试一种方法,它必须执行以下一项操作:

  • return a value you can compare with an expected value 返回可以与期望值进行比较的值
  • change the state of an object which gets passed to it 更改传递给对象的对象的状态
  • throw an exception you can catch 引发您可以捕获的异常
  • change some state of the object which you can verify by calling another method 更改对象的某些状态,您可以通过调用其他方法进行验证

For that reason, methods which returns void and just write their result to System.out should generally be avoided. 因此,通常应避免返回void并将结果只写到System.out的方法。

To fix this issue you can do one of these: 要解决此问题,您可以执行以下操作之一:

  • Return a String instead of writing to stdout. 返回一个String而不是写入stdout。
  • Make the method take an PrintStream object and write to that. 使该方法采用一个PrintStream对象并对其进行写入。 System.out is a PrintStream object, so you can pass it in production code. System.out是一个PrintStream对象,因此您可以在生产代码中传递它。 In your test code, however, you can pass your own PrintStream object which doesn't write to stdout but instead allows to check what was written to it. 但是,在测试代码中,您可以传递自己的PrintStream对象,该对象不写入stdout,而是允许检查写入到其中的内容。 This technique is called Dependency Injection . 这种技术称为依赖注入
  • Make the method write to a private PrintStream or String, and add two new methods to the class. 使该方法写入私有PrintStream或String,然后向该类添加两个新方法。 One to get the content of that variable so you can test that it is correct and one to write that variable to System.out. 一种获取该变量的内容,以便可以测试它的正确性,另一种将该变量写入System.out。

instead of printing your shape directly you could store the shape in an ArrayList<String> 您可以将形状存储在ArrayList<String>而不是直接打印形状

public class Diamond {
    private List<String> shape = null;

    public void createShape(int num) {
        shape = new ArrayList<String>();
        String shapeLine = "";
        for(int ucount=num;ucount>0;ucount--) {
            for(int count_sp=1;count_sp<ucount;count_sp++) {
                shapeLine += " ";
            }
            for(int count_ast=num;count_ast>=ucount;count_ast--) {
                shapeLine += "* ";
            }
            shape.add(shapeLine);
        }

        shapeLine = "";
        for(int lcount=1;lcount<num;lcount++) {
           for(int count_sp=0;count_sp<lcount;count_sp++) {
                shapeLine += " ";
           }
           for(int count_ast=num-1;count_ast>=lcount;count_ast--) {
               shapeLine += "* ";
           }
           shape.Add(shapeLine);
        }
    } 

    public void printShape(OutStream out) {
        if(shape != null) {
            for(String shapeLine : shape) {
                out.println(shapeLine);
            }
        }
    }

    public List<String> getShape() {
        return shape;
    } 
}

now you can test your code: 现在您可以测试您的代码了:

@Test
public void testShape() {
    Diamond diamond = new Diamond();
    diamond.createShape(3);
    List<String> shape = diamond.getShape();

    assertNotNull(shape);
    assertEquals(5, shape.size());
    assertEquals("  * ", shape.get(0));
    assertEquals(" * * ", shape.get(1));
    assertEquals("* * * ", shape.get(2));
    assertEquals(" * * ", shape.get(3));
    assertEquals("  * ", shape.get(4));
}

to print your shape simply call 打印形状只需调用

diamond.printShape(System.out);

the inner part of you loops for the upper and lower half are quite the same and could be refactored into an own method. 上半部分和下半部分的循环内部非常相同,可以将其重构为自己的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM