2

Apache MRUnitを使用すると、クラスターで実行する前に、MapReduce プログラムをローカルで単体テストできます。

私のプログラムはDistributedCacheから読み取る必要があるため、単体テストでモックDistributedCache.getLocalCacheFilesするクラスをラップします。メソッドが呼び出されず、代わりにローカル パスが返されるように、スタブをセットアップします。しかし、メソッドが呼び出されてスローされることがわかりました。 FileNotFoundException

私のMapReduceプログラムは次のようになります

public class TopicByTime implements Tool {
  private static Map<String, String> topicList = null;

  public static void main(String[] args) throws Exception {
   System.exit(ToolRunner.run(new TopicByTime(), args));    
  }

  @Override
  public int run(String[] args) throws Exception {
    Job job = new Job();
    /* Job setup */
    DistributedCache.addCacheFile(new URI(/* path on hdfs */), conf);
    job.waitForCompletion(true);
    return 0;
  }

 protected static class TimeMapper extends Mapper<LongWritable, Text, Text, Text> {    
   @Override
   public void setup(Context context) throws IOException, InterruptedException {
     DistributedCacheClass cache = new DistributedCacheClass();
     Path[] localPaths = cache.getLocalCacheFiles(context.getConfiguration());
     if (null == localPaths || 0 == localPaths.length) {
       throw new FileNotFoundException("Distributed cached file not found");
     }
     topicList = Utils.loadTopics(localPaths[0].toString());

   }

   @Override
   public void map(LongWritable key, Text value, Context context) 
      throws IOException, InterruptedException {
      /* do map */
   }
  }

  /* Reducer and overriding methods */
} 

そして私のテストプログラム

public class TestTopicByTime {

  @Before
  public void setUp() throws IOException {
    Path[] localPaths = { new Path("resource/test/topic_by_time.txt")};
    Configuration conf = Mockito.mock(Configuration.class);
    DistributedCacheClass cache = Mockito.mock(DistributedCacheClass.class);
    when(cache.getLocalCacheFiles(conf)).thenReturn(localPaths); 
   }

  @Test
  public void testMapper() {
  }

  @Test
  public void testReducer() {
  }

  @Test
  public void testMapReduce() {
  }
}

DistributedCacheClassシンプルなラッパーです

public class DistributedCacheClass {
  public Path[] getLocalCacheFiles(Configuration conf) throws IOException {
    return DistributedCache.getLocalCacheFiles(conf);
  }
}

テスト時にローカル パスが読み取られるように Mapper のセットアップ メソッドにフラグを追加することもできましたが、MapReduce プログラムからテスト コードを分割したいと考えています。

Mock Test と MRUnit は初めてなので、プログラムに初心者向けのバグがある可能性があります。バグを指摘してください。修正し、更新内容を以下に投稿します。

4

1 に答える 1

0

あなたのTestTopicByTime.setUp()変更で行

when(cache.getLocalCacheFiles(conf)).thenReturn(localPaths);

when(cache.getLocalCacheFiles(any(Configuration.class))).thenReturn(localPaths);

嘲笑している間、引数は等しくなるように一致します。テストで作成したモック構成と一致しないコードで実際のコンテキストを渡しているため、それらはあなたのケースでは等しくありません。そのため、正確なオブジェクト比較を避けるためにArgument Matcher any()を使用する必要があります。

編集: また、 TimeMapper.setup() で新しいキャッシュを作成しています。 DistributedCacheClass cache = new DistributedCacheClass();

そのため、作成したモック オブジェクトをまったく使用していません。代わりに、モック キャッシュを TimeMapper に挿入できる必要があります。キャッシュ オブジェクトを外部から TimeMapper に、理想的にはコンストラクターを介して渡すことができます。したがって、テストでは、モック キャッシュ オブジェクトを渡すことができます。

于 2013-03-28T04:56:36.673 に答える