代码之家  ›  专栏  ›  技术社区  ›  Caiz22

单元测试时toast中的nullpointerException

  •  0
  • Caiz22  · 技术社区  · 6 年前

    我正在测试注册类的函数,但是每次运行它时,它在第一个if语句中的以下位置输入一个nullpointerException:

    pass.show()
    

    我怀疑这与不使用模拟器测试应用程序有关。在测试时,如何防止创建Toast时出错?

    注册类中的函数:

    public boolean checkInput(String username, String email, String password, String confirmpassword) {
        if (!email.contains("@") || !email.contains(".com")) {
            Toast pass = Toast.makeText(Signup.this, "Email must be valid!", Toast.LENGTH_SHORT);
            pass.show();
            return false;
        }
        if (!password.equals(confirmpassword)) {
            Toast pass = Toast.makeText(Signup.this, "Passwords don't match!", Toast.LENGTH_SHORT);
            pass.show();
            return false;
        }
        if (!(password.length() >= 6)) {
            Toast pass = Toast.makeText(Signup.this, "Password must be at least 6 characters", Toast.LENGTH_SHORT);
            pass.show();
            return false;
        }
        else {
            return true;
        }
    }
    

    试验方法:

        @Test
        public void testInvalidEmail() {
    
        String testUser = "testUser";
        String testEmail = "testEmail.com"; //invalid
        String testPass = "testPass";
        String testConfirmPass = "testPass";
    
        assertFalse(signupClass.checkInput(testUser,testEmail,testPass,testConfirmPass));
    }
    
    3 回复  |  直到 6 年前
        1
  •  0
  •   Elye    6 年前

    你需要脱钩 Toast 从你的职能。要做到这一点,请遵循下面的步骤,在这里我使用您所示的示例,并根据您的需要精确地实现它们。希望这能回答你的询问,并且你能坚持到底。

    首先创建打印(烘烤)界面

    interface Printer {
        void print(String message);
    }
    

    然后制作你的 Signup 类实现 Printer 解耦 干杯 从你的职能。我相信你 注册 是一个 Activity .

    public class Signup extends AppCompatActivity implements Printer {
    
        // ... other codes ...
    
        @Override
        public void print(String message) {
            Toast pass = Toast.makeText(Signup.this, message, Toast.LENGTH_SHORT);
            pass.show();
        }
    }
    

    现在,移除 干杯 在你 checkInput 功能,并通过 printer 发送到函数

    public boolean checkInput(String username, String email, String password, String confirmpassword, Printer printer) {
        if (!email.contains("@") || !email.contains(".com")) {
            printer.print("Email must be valid!");
            return false;
        }
        if (!password.equals(confirmpassword)) {
            printer.print("Passwords don't match!");
            return false;
        }
        if (!(password.length() >= 6)) {
            printer.print("Password must be at least 6 characters");
            return false;
        }
        else {
            return true;
        }
    }
    

    注意:调用的函数 支票输入 从你的班上要派 打印机 ,实际上 this 如果是在 注册 类,例如

    checkInput(testUser, testEmail, testPass, testConfirmPass, this)l;
    

    现在在测试中,只需实现模拟 打印机 例如

    @Test
    public void testInvalidEmail(MainActivity mainActivity) {
    
        String testUser = "testUser";
        String testEmail = "testEmail.com"; //invalid
        String testPass = "testPass";
        String testConfirmPass = "testPass";
    
        assertFalse(signUp.checkInput(testUser, testEmail, testPass, testConfirmPass, new Printer() {
            @Override
            public void print(String message) {
                System.out.println(message);
            }
        }));
    }
    

    有了它,你就可以根据自己的需求进行测试,而你的应用程序仍然可以打印出来。 干杯

        2
  •  1
  •   sebasira    6 年前

    如果你想做的是单元测试,那么你需要将你的代码与Android的东西(比如Toast)分离。

    一种方法是创建一个界面来显示Toast(或处理任何与Android相关的组件),这样您就可以模拟它了。

    例如:

    public interface AndroidInteraction (){
        void showToast(Context context, String text, int length);
    }
    

    并在您的活动中实现该接口:

    public class SignUpActivity extends AppCompatActivity implements AndroidInteraction{
        .......
        ......
    
        @Override
        void showToast(Context context, String text, int length){
             Toast pass = Toast.makeText(context, text, length);
             pass.show();
        }
    

    最后,您的注册类应该知道这个接口,所以您可以通过它传递它的构造函数:

    AndroidInteraction androidInteraction;
    public Signup (AndroidInteraction androidInteraction){
        this.androidInteraction = androidInteraction;
    }
    

    所以您的方法现在看起来像(只有一个if子句来演示如何使用它,而不是整个方法):

    if (!password.equals(confirmpassword)) {
        androidInteraction.showToast(Signup.this, "Passwords don't match!", Toast.LENGTH_SHORT);
        return false;
    }
    

    您需要在测试中模拟该接口并将其传递给类构造函数

        3
  •  -1
  •   Rubick    6 年前

    不要在变量“pass”上传递toast,只需直接键入“toast”并单击第二个建议即可。我还删除了您的返回。

    这是我在您的代码中看到的问题:

    toast pass=toast.maketext(….);

    如果你想把它放到变量上,就这样做

    Toast pass = new Toast(getContext());
    
    
    pass.makeText (.....).show();
    

    pass.makeText(....);
    pass.show();
    

    所以我的建议是选择并尝试一下:

    public boolean checkInput(String username, String email, String password, String confirmpassword) {
    if (!email.contains("@") || !email.contains(".com")) {
        Toast.makeText(Signup.this, "Email must be valid!", Toast.LENGTH_SHORT).show();
    
    }
    if (!password.equals(confirmpassword)) {
       Toast.makeText(Signup.this, "Passwords don't match!", Toast.LENGTH_SHORT).show();
    
    }
    if (!(password.length() >= 6)) {
        Toast pass = Toast.makeText(Signup.this, "Password must be at least 6 characters", Toast.LENGTH_SHORT).show();
       }
    }