Использование ожиданий jmockit с сопоставителями и примитивными типами - PullRequest
4 голосов
/ 18 сентября 2008

Я использую 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";
      }
    }
  }
}
/******************************************************/

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

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

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

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

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

Ответы [ 3 ]

1 голос
/ 18 сентября 2008

Таким образом, проблема, как представляется, в 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 возвращает нуль. Деавтоматическая блокировка примитивного логического значения - это то, откуда приходит NPE.

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

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

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

1 голос
/ 18 июня 2009

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

1 голос
/ 18 сентября 2008

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

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

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

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

...