Метод Mocking, который принимает аргумент типа С помощью JMock

Предыстория:

Это специфический вопрос для JMock + JUnit (это две технологии , которые я должен использовать). Да, то, что я хочу сделать, может быть сделано с PowerMock, но это крайний случай, который не требует смены инструментов. И нет, извините, я не задаю этот вопрос, чтобы обсудить философскую обоснованность статических методов:)

После всего этого я действительно буду благодарен любому, кто взглянет на этот вопрос.

Вопрос:

У меня есть фрагмент унаследованного кода, для которого мне нужно написать тест (мы пытаемся поставить тесты вокруг унаследованного кода, чтобы убедиться, что мы ничего не сломали во время потенциально масштабной работы по рефакторингу. ... это история в другой раз.)

Цель:

Метод, который я пытаюсь смоделировать, - это метод Foo.bar в классе ниже с использованием средства самозащения класса JMock (через JUnit4Mockery .)

Приведенный ниже код является представительным для кода, который я тестирую:

public class Foo {
     public abstract  void bar(
         Class paramClass, T paramT);

Моя тестовая установка направлена ​​на то, чтобы разрешить любое количество вызовов bar() получение экземпляра Class (который явно вырождается в Class ... глупую «особенность» стирания типа Java) в паре с любым экземпляром Snafu.

1128 В этом ключевое различие. Я не соединяю два параметра Matcher или два литеральных параметра, но один литерал (T.class) и любое значение типа T. JMock не допускает этого, поэтому ожидаемое решение ] будет иметь Matcher> и Matcher:

Foo mock = context.mock(Foo.class);
context.checking(new Expectations() {
    // keep warnings close to the culprit code when possible
    @SuppressWarnings("unchecked")
    public void allow(final Foo mockedFoo) {
        allowing(mockedFoo).bar(
            with(any(Snafu.class.getClass())), // Matcher that *should* resolve to Class
            with(any(Snafu.class)));  // matcher to anything of type Snafu.class
    }
    {
        allow(mockedFoo);
    }
});

Затем мы вводим фиктивный Foo, который в конечном итоге будет вызываться так другим классом, который я буду называть Driver (* Я вернусь к вызову статического метода позже):

// fooImpl has been replaced/injected with our mock
fooImpl.bar(Snafu.class, someStaticFunctionThatReturnsASnafu()); 

Проблема:

Проблема заключается в том, что когда Driver вызывает метод bar для смоделированного Foo В моем тесте встречается следующее исключение:

java.lang.IllegalArgumentException: not all parameters were given explicit matchers: either all parameters must be specified by matchers or all must be specified by values, *you cannot mix matchers and values*
    at org.jmock.internal.InvocationExpectationBuilder.checkParameterMatcherCount(InvocationExpectationBuilder.java:98)
    at org.jmock.internal.InvocationExpectationBuilder.createExpectationFrom(InvocationExpectationBuilder.java:91)
    at org.jmock.internal.InvocationToExpectationTranslator.invoke(InvocationToExpectationTranslator.java:19)
    at org.jmock.internal.FakeObjectMethods.invoke(FakeObjectMethods.java:38)
    at org.jmock.lib.legacy.ClassImposteriser$4.invoke(ClassImposteriser.java:129)
    at .....

По-видимому (или мне так кажется), JMock matchers видят Class экземпляры как значения, независимо от того, как мы пытаемся сопоставить их , Или я что-то упускаю?

Я сталкиваюсь с подобными исключениями во многих устаревших вызовах, которые принимают аргумент java.lang.Class. Очевидно, что все, что выглядит как X.class, будет значением, а не новым экземпляром.

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


[*] В идеале можно было бы переписать вызов статического метода в

fooImpl.bar(Snafu.class, someStaticFunctionThatReturnsASnafu()); 

с помощью чего-то более поддающегося насмешке (нестатический метод, другой объект или что-то, введенное с помощью IoC).

Возможно, именно так мы и пойдем, но на данный момент в рассматриваемом коде имеется значительное количество статических вызовов.

Я хотел бы отложить это до более подходящего момента и вместо этого найти общее решение JMock, если таковое существует, которое позволяет мне установить необходимые ожидания для функций имитации, как, например, Foo.bar выше.

]

10
задан luis.espinal 7 April 2014 в 11:54
поделиться