java - 输出流持久化问题

标签 java junit

在使用控制台输入测试 Java 程序时,我创建了一个 ByteArrayOutputStream 并将其设置为系统进行测试。第一个测试执行正确,输出和输入流看起来不错。但是,当第二个测试执行时,输入流无法正确捕获,我不确定为什么。

我尝试过在类构造函数和析构函数中刷新和关闭输出流。清空初始化输入流。

主要

import java.io.*;

public class TriTyp {
   private static String[] triTypes = { "", // Ignore 0.
      "scalene", "isosceles", "equilateral", "not a valid triangle"};
   private static String instructions = "This is the ancient TriTyp program.\nEnter three integers that represent the lengths of the sides of a triangle.\nThe triangle will be categorized as either scalene, isosceles, equilateral\nor invalid.\n";
   public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

public static void main (String[] argv)
{  // Driver program for TriTyp
   int A, B, C;
   int T;

   System.out.println (instructions);
   System.out.println ("Enter side 1: ");
   A = getN();
   System.out.println ("Enter side 2: ");
   B = getN();
   System.out.println ("Enter side 3: ");
   C = getN();
   T = triang (A, B, C);

   System.out.println ("Result is: " + triTypes[T]);
}

private static int triang (int Side1, int Side2, int Side3)
{
   if (Side1 <= 0 || Side2 <= 0 || Side3 <= 0)
   {
      triOut = 4;
      return (triOut);
   }

   triOut = 0;
   if (Side1 == Side2)
      triOut = triOut + 1;
   if (Side1 == Side3)
      triOut = triOut + 2;
   if (Side2 == Side3)
      triOut = triOut + 3;
   if (triOut == 0)
   {
     if (Side1+Side2 <= Side3 || Side2+Side3 <= Side1 ||
        Side1+Side3 <= Side2)
        triOut = 4;
     else
        triOut = 1;
     return (triOut);
   }

   if (triOut > 3)
      triOut = 3;
   else if (triOut == 1 && Side1+Side2 > Side3)
      triOut = 2;
   else if (triOut == 2 && Side1+Side3 > Side2)
      triOut = 2;
   else if (triOut == 3 && Side2+Side3 > Side1)
      triOut = 2;
   else
      triOut = 4;
   return (triOut);
}

private static int getN ()
{
   int inputInt = 1;
   String inStr;

   try
   {
      inStr    = in.readLine ();
      inputInt = Integer.parseInt(inStr);
   }
   catch (IOException e)
   {
      System.out.println ("Could not read input, choosing 1.");
   }
   catch (NumberFormatException e)
   {
      System.out.println ("Entry must be a number, choosing 1.");
   }

   return (inputInt);
}
}

测试

import java.io.*;
import java.util.Arrays;
import static org.junit.Assert.*;
import org.junit.*;
import java.nio.charset.StandardCharsets;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class TriTypTest {
    private PrintStream originalOut = System.out;
    private PrintStream originalErr = System.err;
    private InputStream originalIn = System.in;

    private ByteArrayOutputStream outContent = new ByteArrayOutputStream();

    @Before
    public void setUp() throws Exception {
        outContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(outContent));
    }

    @After
    public void tearDown() throws Exception {
        System.out.flush();
        System.setOut(originalOut);
    }

    @Test
    public void TestEquilateral() {
        // Set up input of an equilateral triangle for TriTyp.main()
        // String mockinput = "3" + System.lineSeparator() + "3" + System.lineSeparator() + "3";
        String mockinput = "3\r\n3\r\n3";
        ByteArrayInputStream in = new ByteArrayInputStream(mockinput.getBytes());
        // Set up mock user input stream
        System.setIn(in);

        // Initialize the TriTyp.main(input) method
        String[] mainin = {};
        TriTyp.main(mainin);

        // Capture the standard output
        String triout = outContent.toString();
        String[] chopout = triout.split(System.lineSeparator());
        String triangletype = chopout[chopout.length - 1];

        // Call assert for equilateral triangle output
        assertEquals("Result is: equilateral",triangletype);
    }

    @Test
    public void TestScalene() throws Exception {
        // Set up input of an equilateral triangle for TriTyp.main()
        String mockinput = "3\r\n4\r\n2";
        ByteArrayInputStream in = new ByteArrayInputStream(mockinput.getBytes());
        // Set up mock user input stream
        System.setIn(in);

        // Initialize the TriTyp.main(input) method
        String[] mainin = {};
        TriTyp.main(mainin);

        // Capture the standard output
        String triout = outContent.toString();
        String[] chopout = triout.split(System.lineSeparator());
        String triangletype = chopout[chopout.length - 1];

        // Call assert for equilateral triangle output
        assertEquals("Result is: scalene", triangletype);
    }
}

上次测试断言失败:

org.junit.ComparisonFailure: 预期:结果是:scalene 实际:结果是:等边

最佳答案

您的问题在这里:

public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

在您的测试中,您使用模拟输入创建一个新的 Reader,并将 System.in 替换为它。问题是这个静态成员仅创建一次,并且不会被新的模拟替换。这会导致它在后续读取时返回 null,默认值为 1,从而导致错误的输出。

我建议的修复方法是删除静态,注入(inject)阅读器,以便可以替换它并仅使用 main 作为组合根。

public class TriTyp {
    private static String[] triTypes = {"", // Ignore 0.
        "scalene", "isosceles", "equilateral", "not a valid triangle"};
    private static String instructions = "This is the ancient TriTyp program.\nEnter three integers that represent the lengths of the sides of a triangle.\nThe triangle will be categorized as either scalene, isosceles, equilateral\nor invalid.\n";

    private final BufferedReader in;

    public TriTyp(BufferedReader in) {
        this.in = in;
    }

    public static void main(String[] argv) {
        new TriTyp(new BufferedReader(new InputStreamReader(System.in))).run();
    }

    public void run() {
        int A, B, C;
        int T;

        System.out.println(instructions);
        System.out.println("Enter side 1: ");
        A = getN();
        System.out.println("Enter side 2: ");
        B = getN();
        System.out.println("Enter side 3: ");
        C = getN();
        T = triang(A, B, C);

        System.out.println("Result is: " + triTypes[T]);
    }

    // Triang and getN methods. Just drop their static keyword.
}

在测试中您将替换它:

String mockinput = "3\r\n3\r\n3";
ByteArrayInputStream in = new ByteArrayInputStream(mockinput.getBytes());
// Set up mock user input stream
System.setIn(in);

// Initialize the TriTyp.main(input) method
String[] mainin = {};
TriTyp.main(mainin);

这样:

String mockinput = "3\r\n3\r\n3";
ByteArrayInputStream in = new ByteArrayInputStream(mockinput.getBytes());
new TriTyp(new BufferedReader(new InputStreamReader(in))).run();

关于java - 输出流持久化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56503457/

相关文章:

java - 如何向 Oracle 触发器发送任意参数?

eclipse - 将 JUnit 与 App Engine 和 Eclipse 结合使用

java - JUnit 测试 Java 代码断言是否失败

java - 在Android Studio中添加Junit测试(从Eclipse导入的项目)

java - EasyMock 缺少行为,即使它已定义

java - Android: Unresolved 依赖关系

java - 使用 StdDeserializer Jackson 2.5 处理多态

java - 是否可以让 Antlr4 从基本语法词法分析器而不是生成词法分析器生成词法分析器?

java - 为什么使用 BigInteger 的程序不显示任何内容?

java - 以非静态方式创建 JUnit TestSuite