Аргумент (ы) разные! В розыске: - PullRequest
0 голосов
/ 21 октября 2019

Я пишу модульный тест для моего кода ниже

public class Class1 {
   protected void execute(String a, String b) {
   try{
      process(a,b);
   }
   catch(Exception E){
       Class2.write(e,Class1.class.getSimpleName())
    }
  }

  private void process(String a, String b) {
     validate(a,b);
     // Doing some processing on a and b values
  }

 private void validate (String a, String b) {
    if(a==null || a.isEmpty() || b==null || b.isEmpty())
       throw new IllegalArgumentException("Input value cannot be null or empty");
 }

}

Для кода выше, я пытаюсь написать UT, который охватывает случай использования исключения. Ниже приведен мой код UT:

@Test

public void test1(){
 try {

            PowerMockito.mockStatic(Class2.class);
            PowerMockito.when(Class2.class, "write", Mockito.anyObject(), Mockito.anyString())
                    .thenCallRealMethod();
            Class1 class1 = new Class1();
            Class2.write(new IllegalArgumentException("Input value cannot be null or empty"),Class1.class.getSimpleClassName());
            PowerMockito.verifyStatic(Class2.class, VerificationModeFactory.times(1));
            class1.execute(Mockito.anyString(),Mockito.anyString());  
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
}

При выполнении вышеуказанного теста я получаю исключение, указанное ниже

Argument(s) are different! Wanted:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}

Actual invocation has different arguments:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}

Может кто-нибудь помочь мне решить эту проблему? Я очень ценю вашу помощь и время

Заранее спасибо

1 Ответ

0 голосов
/ 21 октября 2019

Ваша проблема:

IllegalArgumentException не использует строковое сообщение для равенства. Было бы безопаснее проверить строковое сообщение или тип класса. Я бы предпочел, чтобы тест определял тип, а не сообщение, так как строковое сообщение не должно использоваться для потока управления, это деталь реализации.

System.out.println(Objects.equals(
    new IllegalArgumentException(), 
    new IllegalArgumentException()));
// false

System.out.println(Objects.equals(
    new IllegalArgumentException().getClass(),
    new IllegalArgumentException().getClass()));
// true

Поэтому, чтобы смоделировать это, я бы использовал matchers:

any(IllegalArgumentException.class), eq(Class1.class.getSimpleName())

Проблемы с вашим дизайном:

Я собираюсь закончить аргументом против того, как этот код структурирован, так как он не построен на основе внедрения зависимостей. Вместо вызова статического метода Class2::write вы можете вызывать метод экземпляра.

Например, создайте интерфейс:

public interface Writer {
    void write(Exception e, String source);
}

Теперь вы можете реорганизовать класс для предоставления двух ctors, один из которых принимает любого писателя, а другой по умолчанию Class2.

public class Class1 {
    private final Writer writer;

    public Class1() {
        this(Class2::write);
    }

    public Class1(Writer writer) {
        this.writer = writer;
    }

    protected void execute(String a, String b) {
        try {
            process(a,b);
        }
        catch (Exception E) {
            writer.write(e, Class1.class.getSimpleName());
        }
    }
    ...
}

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

По моему мнению, большинство PowerMockito / PowerMockтолько помогите проверить код, который не был построен с учетом тестируемости / гибкости. Вам не нужно использовать что-либо за пределами набора инструментов Mockito / EasyMock для хорошо структурированного кода. Есть некоторые исключения, но набор инструментов должен использоваться очень экономно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...