如何测试在 jUnit 控制台上打印的 void 方法?

How to test a void method that prints on console in jUnit?

我使用工厂模式。我有 3 种货币:美元、罗马尼亚列伊和欧元。在每个 classes 中,我都有相同的功能,打印,但输出不同:

public void print() {
    System.out.println("I printed dollars!");

}

     public void print() {
    System.out.println("I printed euro!");}

在我的工厂 class 中,我有一个方法 return 一个新的货币类型对象:

    public Valuta getValuta(String numeValuta){
    if(numeValuta == null){
        return null;
    }
    if(numeValuta.equalsIgnoreCase("dolar")){
        return new Dolar();
    }
    if(numeValuta.equalsIgnoreCase("euro")){
        return new Euro();
    }
    if(numeValuta.equalsIgnoreCase("lei")){
        return new Lei();
    }
    return null;
}

现在,在我的测试 class 中,我尝试测试这个:

    FabricaBani fabrica = new FabricaBani();
    Valuta valuta = fabrica.getValuta("dolar");
    valuta.tipareste();
    assertEquals("I printed dollars!", valuta.print());

我收到一条错误消息,提示我无法测试带有 void 的字符串。我尝试在 valuta.print 之后放置 .toString,但不允许这样做。

方法 valuta 没有 return 任何东西,这就是为什么 valuta.print() 不能是您输出到控制台的字符串。

如果你想测试这个值,你可以将你的方法重构为 return 字符串而不是输出它;然后您将在调用 print().

的方法中打印 returned 字符串
public String print() {
    return "I printed dollars!";
}

 public void print() {
  return "I printed euro!";
 }

然后,你会像这样调用打印输出到控制台

System.out.println(valuta.print());

您可以将打印方法重命名为 getCurrency 以更好地表达该方法的作用。

您可以编写一个调用 setOut 来捕获打印输出的测试,如下所示:

private static void test() {
    System.out.println("Hello, world!");
}
public static void main (String[] args) throws java.lang.Exception
{
    String res = null;
    PrintStream originalOut = System.out;
    try {
        ByteArrayOutputStream os = new ByteArrayOutputStream(100);
        PrintStream capture = new PrintStream(os);
        // From this point on, everything printed to System.out will get captured
        System.setOut(capture);
        test();
        capture.flush();
        res = os.toString();
    } finally {
        System.setOut(originalOut);
    }
    System.out.println("Captured output: "+res);
}

Demo.

这远非理想,只有当您没有其他方法来测试相关功能时才应使用 - 例如,当您无法控制执行输出的部分代码时。

另一方面,这种方法可以让您测试必须进行一些打印的代码的副作用,因此在您的测试必须确保输出到 System.out.

的情况下,它可能是相关的

对于这种情况,一个很好的替代方案可能是 扩展美元 (或一个人继承 class)以进行测试。然后,当调用 print() 方法时,您可以存储最后打印的字符串。

// Inside class extending Dollar, for example
// public class TestDolar extends Dollar
@Override
public void print() {
  _printedMessage = Valuta.DOLLAR_MESSAGE
}

这可能意味着您可以将打印消息存储在 Valuta 或单独的 classes 中。

//Inside Dollar
public void print() {
  System.out.println(Valuta.DOLLAR_MESSAGE);
}

//Inside Valuta
public static final String DOLLAR_MESSAGE = "I printed dollars!";