Использование ожиданий jmockit для сопоставлений и примитивных типов

StackOverflow https://stackoverflow.com/questions/88743

Вопрос

Я использую jmockit для модульного тестирования (с TestNG), и у меня возникли проблемы с использованием класса Expectations для имитации метода, который принимает примитивный тип (логический) в качестве параметра, используя средство сопоставления.Вот пример кода, иллюстрирующий проблему.

/******************************************************/
import static org.hamcrest.Matchers.is;

import mockit.Expectations;

import org.testng.annotations.Test;

public class PrimitiveMatcherTest {
  private MyClass obj;

  @Test
  public void testPrimitiveMatcher() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo(with(is(false))), "bas");
      }
    };

    assert "bas".equals(obj.getFoo(false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(boolean arg) {
      if (arg) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}
/******************************************************/

Строка, содержащая вызов метода ignoreReturning(...), вызывает исключение NullPointerException.

Если я изменю этот вызов, чтобы не использовать сопоставитель, как в:

invokeReturning(c.getFoo(false), "bas");

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

Я почти уверен, что это ошибка, или, возможно, невозможно использовать Matchers с примитивными типами (это меня расстроило бы).Кто-нибудь сталкивался с этой проблемой и знает, как ее обойти?

Это было полезно?

Решение 2

Итак, проблема, похоже, в Expectations.with():

   protected final <T> T with(Matcher<T> argumentMatcher)
   {
      argMatchers.add(argumentMatcher);

      TypeVariable<?> typeVariable = argumentMatcher.getClass().getTypeParameters()[0];

      return (T) Utilities.defaultValueForType(typeVariable.getClass());
   }

Вызов typeVariable.getClass() не делает того, что ожидает автор, а вызов типа Utilities.defaultValueFor возвращает значение null.Деавтобоксирование обратно к примитивному логическому значению — вот откуда берется NPE.

Я исправил это, изменив вызов ignoreReturning(...) на:

invokeReturning(withEqual(false)), "bas");

Я больше не использую здесь сопоставление, но оно достаточно хорошо для того, что мне нужно.

Другие советы

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

Код Matchers основан на Generic, который в основном не поддерживает примитивные типы.Обычно Matchers используются больше для сопоставления значений;с функцией автоматической упаковки/распаковки в Java 5 это обычно не является проблемой.

Но ожидание JMockit не использует его для сопоставления значения, оно использует его для какого-то анализа, чтобы определить тип сигнатуры вызова метода... что в этом случае Matchers приведет к логическому типу, в то время как ваш метод является примитивным типом... поэтому он терпит неудачу чтобы посмеяться над этим как следует.

Мне жаль, что я не могу подсказать вам обходной путь для этой проблемы.Может быть, кто-то еще сможет помочь.

Я изменил JMockit (выпуск 0.982), так что «with(is(false))» и другие подобные варианты теперь работают должным образом (он больше не возвращает ноль, а фактическое значение аргумента внутри внутреннего сопоставителя).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top