NullPointerException от Toast при модульном тестировании - PullRequest
0 голосов
/ 11 сентября 2018

Я тестирую функцию моего класса Registration, однако каждый раз, когда я ее запускаю, внутри первого оператора if возникает исключение NullPointerException:

pass.show()

Я подозреваю, что это как-то связано с нетестирование приложения с помощью эмулятора.Как я могу предотвратить ошибки при создании тоста, когда я тестирую это?

Функция в классе регистрации:

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 ]

0 голосов
/ 11 сентября 2018

Вместо того, чтобы передавать Toast по переменной 'pass', просто наберите '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();
   }
}
0 голосов
/ 11 сентября 2018

Вам нужно отделить Toast от вашей функции.Чтобы сделать это, выполните шаг ниже, где я использую ваш показанный пример и реализую их точно так, как вам нужно.Надеемся, что ответ на ваш запрос, и вы могли бы выполнить.

Сначала создайте интерфейс для печати (тост)

interface Printer {
    void print(String message);
}

Затем сделайте ваш класс Signup реализует Printerотделить Toast от вашей функции.Я полагаю, что ваш Signup является 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();
    }
}

Затем удалите Toast из функции 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;
    }
}

Примечание: любую функцию, которая вызывает checkInput из вашего класса, нужно будет отправить в Printer, что на самом деле this, если оно в Signup классе, например

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

Теперь в вашем тесте, просто внедрите макет Printer например

@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);
        }
    }));
}

С этим вы можете выполнить свой тест по своему желанию, в то время как ваше приложение все еще печатает через Toast

0 голосов
/ 11 сентября 2018

Если вы хотите использовать UnitTesting, то вам нужно отделить свой код для 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;
}

И вам нужно будет смоделировать этот интерфейс в тесте и передать его конструктору класса

...