英文:
Junit test for scanner parameter filereader
问题
I will only provide translations for the non-code parts of your text:
"What I am trying to do is to simply write a test for the calcGrade(scanner sc) function, but I don't know if it's possible to test it in this scenario since the scanner reads in grades in a textfile then returns an average of them."
我试图做的是简单地为calcGrade(scanner sc)函数编写一个测试,但我不知道在这种情况下是否可以测试它,因为扫描器从文本文件中读取成绩然后返回它们的平均值。
"grade.txt"
grade.txt
英文:
What I am trying to do is to simply write a test for the calcGrade(scanner sc) function, but I don't know if it's possible to test it in this scenario since the scanner reads in grades in a textfile then returns an average of them.
public static void main(String[] args) throws FileNotFoundException {
        
        Scanner sc = new Scanner(new FileReader("./Src/Chapter3/grade.txt"));
        
        System.out.printf("The average grade is: %.2f", calcGrade(sc));
                
    }
    public static double calcGrade(Scanner sc) {
        double test1, test2, test3, test4, test5, avg;
        test1 = sc.nextDouble();
        test2 = sc.nextDouble();
        test3 = sc.nextDouble();
        test4 = sc.nextDouble();
        test5 = sc.nextDouble();
        avg = (test1 + test2 + test3 + test4 + test5) / 5.0;
        
        sc.close();
        return avg;
    }
 @Test
    public void testCalGrade() {
    double expected = 70.0;
    double actual = js.calcGrade(); //i could change the parameter here instead passed in scanner to the individual grades then test it
    assertEquals(expected, actual,0.02);
}
grade.txt
80 98 100 78 65.6
答案1
得分: 0
由于Scanner是一个最终类,您无法在测试中提供模拟(或任何虚假对象)来代替使用真实的Scanner对象。
理论上,您仍然可以使用外部库(如PowerMock)创建模拟对象或更改System.in字段,但更好的方法是使calcGrade方法更加通用。例如,它可以接受Supplier<Double>而不是Scanner。这是一个示例。
public static double calcGrade(Supplier<Double> valueSupplier) {
    double test1, test2, test3, test4, test5, avg;
    test1 = valueSupplier.get();
    test2 = valueSupplier.get();
    test3 = valueSupplier.get();
    test4 = valueSupplier.get();
    test5 = valueSupplier.get();
    avg = (test1 + test2 + test3 + test4 + test5) / 5.0;
    return avg;
}
然后您可以这样调用它
public static void main(String[] args) throws FileNotFoundException {
    Scanner sc = new Scanner(new FileReader("./Src/Chapter3/grade.txt"));
    System.out.printf("The average grade is: %.2f", calcGrade(sc::nextDouble));
    sc.close();
}
如果您不了解sc::nextDouble语法,它被称为方法引用,当调用valueSupplier.get()时,它基本上调用sc.nextDouble()。
然后,您可以这样测试它
public class CalGradeTest {
    private int index;
    @Test
    public void testCalGrade() {
        CalGrade js = new CalGrade();
        double[] testValues = {68.0, 69.0, 70.0, 71.0, 72.0};
        double expected = 70.0;
        double actual = js.calcGrade(() -> testValues[index++]);
        assertEquals(expected, actual, 0.02);
    }
}
英文:
Since Scanner is a final class, you cannot provide a mock (or any fake object) instead of using a real Scanner object in the test.
Though theoretically you still could create a mock using external libraries (like PowerMock) or change the System.in field, a better way would be to make the calcGrade method more generic.
E.g. it could accept a Supplier<Double> instead of a Scanner. Here is an example.
    public static double calcGrade(Supplier<Double> valueSupplier) {
        double test1, test2, test3, test4, test5, avg;
        test1 = valueSupplier.get();
        test2 = valueSupplier.get();
        test3 = valueSupplier.get();
        test4 = valueSupplier.get();
        test5 = valueSupplier.get();
        avg = (test1 + test2 + test3 + test4 + test5) / 5.0;
        return avg;
    }
Then you can call it like this
    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc = new Scanner(new FileReader("./Src/Chapter3/grade.txt"));
        System.out.printf("The average grade is: %.2f", calcGrade(sc::nextDouble));
        sc.close();
    }
If you don't know the sc::nextDouble Syntax, it's called a method reference and basically calls sc.nextDouble() when valueSupplier.get() is called.
Then you could test it like this
public class CalGradeTest {
    private int index;
    @Test
    public void testCalGrade() {
        CalGrade js = new CalGrade();
        double[] testValues = {68.0, 69.0, 70.0, 71.0, 72.0};
        double expected = 70.0;
        double actual = js.calcGrade(() -> testValues[index++]);
        assertEquals(expected, actual, 0.02);
    }
}
答案2
得分: 0
Here's the translated content:
扫描器有多个构造函数,因此您可以选择一个不同的构造函数并使用它。
以下是您如何修改测试的示例
@Test
public void testCalGrade() {
   double expected = 70.0;
   double actual = js.calcGrade(new Scanner("80 98 100 78 65.6"));
   assertEquals(expected, actual, 0.02);
}
英文:
Scanner has multiple constructors, so you can choose a different one and use that.
Example of how you can modify your test
 @Test
 public void testCalGrade() {
    double expected = 70.0;
    double actual = js.calcGrade(new Scanner("80 98 100 78 65.6"));
    assertEquals(expected, actual,0.02);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论