在不更改其他人的类的情况下,如何要求它使用我的Scanner版本(作为内部类掩埋)而不是java.util.Scanner?

问题描述 投票:0回答:1

为了娱乐(并在课堂上用作教学工具),我正在编写类似于JUnitTests的程序。我想用它对高中生编写的代码进行测试。当学生编写使用Scanner通过System.in获取用户输入的代码时,我想“劫持” Scanner以提供我自己的预定用户输入。除了让我的扫描仪成为AutoTester的内部类的愿望之外,我的所有工作都很好。

下面的示例大大简化了,但很清楚。

比方说,一个学生写了这段代码:

import java.util.*;
public class Practice {  
    public static void practiceScanners()  {
        Scanner console = new Scanner(System.in);                 
        System.out.print("Type first name, age, and address >> ");
        String name = console.next();
        int age = console.nextInt();
        String address = console.nextLine();
        System.out.println(name + " is " + age + " and lives at" + address + ".");
    }
}

然后,假设我有一个名为AutoTester的类,看起来像这个伪代码:

public class AutoTester {

    public main() {
        * use JavaCompiler from ToolProvider to compile Practice.java
        * use reflection to invoke Practice.practiceScanners()
             * (hopefully) have student code use my Scanner instead of java.util.Scanner
             * collect output of running the student code 
             * compare against expected output
    }

    //My version of Scanner is an inner class within AutoTester
    public class Scanner { 
        private String script = "Bob 13 42 Maple Drive";
        <* implementation not shown *>    
    }

}

如果将我的Scanner版本移动到它自己的Scanner.java文件中,则可以正常工作。学生代码在查看java.util之前使用我的(本地)扫描程序。但是,当我将Scanner作为内部类移入AutoTester时,学生代码不知道要在那里寻找它。而且我也不想以任何方式编辑学生代码(例如将“扫描仪”实例化行更改为新的AutoTester.Scanner(System.in))

在编译/运行学生程序而不对他们的代码进行任何编辑时,有没有办法让我的AutoTester.Scanner优先于java.util.Scanner?

java inner-classes
1个回答
1
投票

不幸的是,这种方式行不通。自定义扫描程序的类名称实际上是AutoTester.Scanner,您在测试类中定义了它,除了看起来相似的名称之外,它与java.util.Scanner没有任何关系。因此,这根本不影响Practice

您必须重组Practice代码,才能将@Inject(例如CDI与)用作扫描仪。然后使用mockito@Mock, @InjectMocks)连接扫描仪。不过,那是很多重型机械。作为替代方案,您可以设计Practice,以使其将Scanner作为构造函数参数或作为属性。

但是您仍然有问题,扫描程序是无法扩展的最终课程。因此,您必须为此目的引入自己的接口,在一种情况下将java.util.Scanner置于幕后,而在另一种情况下将其替换为Scanner。

© www.soinside.com 2019 - 2024. All rights reserved.