6

java.nio.file.Filesをモックしようとする次のサンプル単体テストがありますが、このモックは機能せず、コードはサンプルパスを削除しようとします。

@Test
    public void testPostVisitDirectory() throws Exception {
        Path mockedPath = Paths.get("sample path");
        PowerMockito.mockStatic(Files.class);
        PowerMockito.doNothing().when(Files.class,
                PowerMockito.method(Files.class, "delete", Path.class));

        DeleteDirVisitor visitor = new DeleteDirVisitor(false);
        Assert.assertEquals("The was a problem visiting the file",
                FileVisitResult.CONTINUE,
                visitor.postVisitDirectory(mockedPath, null));
    }

何が悪いのか分かりますか?

これがメソッドの内容ですvisitor.postVisitDirectory

[...]
if (e == null) {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
[...]

ありがとう、

4

3 に答える 3

5

powermock 1.5.1 と Files クラスを使用して同様の問題が発生しましたが、理由はわかりませんが、一部/すべての jdk1.7 クラスを静的にモックする問題があると思われます。javassistのバージョンも確認したところ、当時は最新(3.18.0-GA)でしたが、

テスト対象のクラスを Files 行だけに削除しましたが、それでも機能しませんでした。次に、別の静的クラス StringUtils.chop("string"); のモックを作成することにしました。(commons-lang3)そして、私のパワーモックテストが機能し、モックから例外を生成するように強制することができました.

これは、私が本ですべてを行ったこと、およびその静的モッキングが Files クラスでは機能しなかったが、StringUtils では機能したことを証明しました。

ちなみに、@PrepareForTest と PowerMockito.mockStatic() 呼び出しの両方を変更して、正しいクラスを参照しました。

最後に、ファイルのモックをあきらめました。他の誰かが同じ問題を抱えている場合に備えて、注意してください。

編集。うまくいきました:別のプロジェクトで必要になったので、これをもう一度試しました。別のコメントへの返信で言及したバグを修正する更新された javassist (3.18.1-GA) を使用する PowerMock out (1.5.3) の新しいバージョンがあります。

テスト中のクラスが静的メソッドを公開していない場合でも、テストFiles対象のクラスを追加することで、一貫してモックを機能させることができます。以前は、他の静的モックのためにこれを行う必要はありませんでした。なぜそれが必要なのか、.@PrepareForTestFilesFiles

例:

public class MyTestClass {

    public void justToTestMocking(Path path) throws IOException {
        if (!Files.exists(path)) {
            throw new IllegalArgumentException("I know there is a deleteIfExists() but I am just testing mocking");
        }
        Files.delete(path);
    }
}

そして以下のテスト:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Files.class, MyTestClass.class})
public class MyTestClassTest {

    @Before
    public void setUp() {
        mockStatic(Files.class);

    }        

    @Test
    public void justToTestMocking_WillDeletePath() throws IOException {
        Path path = mock(Path.class);
        MyTestClass test = new MyTestClass();

        when(Files.exists(path)).thenReturn(true);

        test.justToTestMocking(path);

        verifyStatic();
        Files.delete(path);
    }
}
于 2013-07-11T06:03:15.993 に答える
4

追加しましたか

@RunWith(PowerMockRunner.class)
@PrepareForTest(Files.class)

そのメソッドを含むjunitテストクラスに?

powermockのドキュメントの「テストの作成」セクションを参照してください。

編集:

うーん、あなたはすべてを正しくやっているようです。これが私が実行しているものです:

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Files.class)
public class TestVisitor {
  public class PrintingVisitor extends SimpleFileVisitor<Path> {
    @Override
    public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
      Files.delete(dir);
      return FileVisitResult.CONTINUE;
    }
  }

  @Test
  public void testPostVisitDirectory() throws Exception {
    final Path mockedPath = Paths.get("sample path");

    /* Mocking */
    PowerMockito.mockStatic(Files.class);
    PowerMockito.doNothing().when(Files.class, PowerMockito.method(Files.class, "delete", Path.class));
    /* End Mocking */

    final PrintingVisitor visitor = new PrintingVisitor();
    Assert.assertEquals("The was a problem visiting the file", FileVisitResult.CONTINUE, visitor.postVisitDirectory(mockedPath, null));
  }
}

Mockingというラベルの付いたセクションをコメントアウトすると、が表示されNoSuchFileExceptionます。そのままにしておくと、テストに合格します。

おそらく、エラーを生成する完全な例を投稿しますか?

于 2013-02-19T20:57:05.657 に答える
1

同様の問題がありましたが、正しいクラスの準備に関連していたことが判明しました。

上記の例では、テストされたクラスは、テスト クラスの内部クラスであるため、既に "prepareFor-Scope" に含まれていました。

静的メソッドを呼び出すクラスを追加する必要があります...私の場合、アクセスしたコードが明示的に準備できない匿名クラス内にあった@PrepareForTestため、これらは十分ではありませんでした。Files.delete

匿名クラスに名前を付けて追加すると@PrepareForTest、すべてが機能しました

于 2013-07-05T08:36:48.020 に答える