MapReduce - макет с мокито - PullRequest
       6

MapReduce - макет с мокито

0 голосов
/ 10 февраля 2020

У меня есть класс редуктора, который я хотел написать тестовые случаи:

Сократить класс:

public class MyReducer extends Reducer<Text, Text, NullWritable, Text> {
    private static final Logger LOG = LogManager.getLogger(MyReducer.class);
    public static List<String> l1 = new ArrayList<String>();
    String id = null;
    private MultipleOutputs<NullWritable, Text> mos;

    @Override
    public void setup(final Context context) throws IOException, InterruptedException {
        mos = new MultipleOutputs<NullWritable, Text>(context);

         final Path[] uris = DistributedCache.getLocalCacheFiles(context.getConfiguration());

        try {
            final BufferedReader readBuffer1 = new BufferedReader(new FileReader(uris[0].toString()));
            String line;
            while ((line = readBuffer1.readLine()) != null) {
                l1.add(line);
            }
            readBuffer1.close();
        } catch (Exception e) {
            LOG.error(e);
        }
    }

    public void reduce(final Text key, final Iterable<Text> values, final Context context)
            throws IOException, InterruptedException {

        final String[] key1 = key.toString().split("-");
        final String keyA = key1[10];
        final String date = key1[1];

/* Some condition check */ 

           mos.write(NullWritable.get(), new Text(inputEventValue), keyA + "//date=" +
                    date.substring(0, 4) + "-" + date.substring(4, 6));

       }

    @Override
    public void cleanup(final Context context) throws IOException, InterruptedException {
        mos.close();
    }

}

Тестовый случай выглядит так:

@RunWith(MockitoJUnitRunner.class)
public class MyTest {

   @Mock
    private MyReducer.Context mockContext;

    MyReducer reducer;
    MultipleOutputs<NullWritable, Text> mos;

    @Before
    public void setUp() {
        reducer = new MyReducer();
    }


   @Test
    public void myReducerTest() throws Exception {

        MyReducer spy = PowerMockito.spy(new MyReducer());
        doNothing().when(spy).setup(mockContext);

        mos = new MultipleOutputs<NullWritable, Text>(mockContext);
        List<Text> sline = new ArrayList<>() ;
        List<String> l1 = new ArrayList<String>();
        l1.add(“1234”);
        sline.add(new Text(“xyz”));
        Whitebox.setInternalState(MyReducer.class,”l1", l1);
        Whitebox.setInternalState(MyReducer.class,"mos",mos);
        reducer.reduce(new Text(“xyz-20200101-1234),sline,mockContext);

    }

    @After
    public void tearDown() throws Exception {
        /*
         * this will do the clean up part
         */
        verifyNoMoreInteractions(mockContext);
    }

Когда работает в режиме отладки, он переходит к методу редуктора и завершается с NullPointerException, где оператор записи Mos равен?

Завершить трассировку стека:

java.lang.NullPointerException
    at org.apache.hadoop.mapreduce.lib.output.MultipleOutputs.getNamedOutputsList(MultipleOutputs.java:196)
    at org.apache.hadoop.mapreduce.lib.output.MultipleOutputs.<init>(MultipleOutputs.java:324)
    at MyTest.myeducerTest
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)

Пересмешивать ошибки Mos, так как Mos не является стат c.

Любое предложение.

Junit - ReduceDriver, withInput, withOutput,testRun  doesn't work.

Спасибо.

Я попытался смоделировать несколько выходов, как было предложено:

import org. apache .had oop .mapreduce.lib.output.MultipleOutputs;

@ Mock private MyReducer .Context mockContext;

    List<String> namedOut = new ArrayList<>();
    namedOut.add("NM1");
    namedOut.add("NM2");

MultipleOutputs spy = PowerMockito.spy (new MultipleOutputs <> (mockContext)); when (spy, "getNamedOutputsList (mockContext)"). thenReturn (namedOut);

Но это дает мне ошибку: org.powermock.reflect.exceptions.MethodNotFoundException: метод не найден с именем 'getNamedOutputsList (() anyObject ()) 'с типами параметров: [] в классе org. apache .had oop .mapreduce.lib.output.MultipleOutputs.

1 Ответ

0 голосов
/ 10 февраля 2020

Похоже, вы не определили, что mockContext.getContext() должно возвращать для вашего теста, поэтому он возвращает null и завершается ошибкой.

На основании этого исходного кода методы выглядят следующим образом ( так что вы могли бы использовать другую версию):

private static List<String> getNamedOutputsList(JobContext job) {
   List<String> names = new ArrayList<String>();
   StringTokenizer st = new StringTokenizer(
     job.getConfiguration().get(MULTIPLE_OUTPUTS, ""), " ");
   while (st.hasMoreTokens()) {
     names.add(st.nextToken());
   }
   return names;
}

JobContext, кажется, относится к вашему макету Reducer.Context mockContext, поэтому вам нужно определить соответствующее поведение, чтобы оно возвращало то, что оно должно было вернуть.

Обратите внимание, что этот вызов происходит из конструктора MultipleOutputs.

Также обратите внимание на метод stati c getCountersEnabled, который вызывается из конструктора и взаимодействует с контекстом.


Насмешливые ошибки MOS, поскольку MOS - это не состояние c.

Вы, вероятно, можете использовать отражения, чтобы вставить в ваш макет версию mos. MyReducer class.

Проверьте здесь , чтобы узнать, как смоделировать частное поле c.


Редактировать:

Если вы попытаетесь издеваться над конигом, сделайте это так:

Configuration config = Mockito.mock(Configuration.class);
when(mockContext.getConfiguration()).thenReturn(config);

Насколько я вижу get которые вызываются в объекте конфигурации, всегда предоставляют значение по умолчанию, поэтому не должно иметь значения, есть пара ключ / значение или нет.

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