Saya telah melihat pertanyaan berikut dan itu tidak sama dengan pertanyaan saya:
jMockit: Bagaimana cara mengharapkan panggilan konstruktor ke objek yang diolok-olok?
Pertanyaan ini serupa tetapi jawabannya tidak membantu saya:
Cara meniru konstruktor default Kelas kencan dengan JMockit?
Apa yang saya coba lakukan adalah meniru panggilan konstruktor ke java.util.zip.ZipFile
, khususnya yang memiliki argumen java.io.File
. Saya ingin konstruktor mengembalikan instance ZipFile
yang berbeda, yang akan saya contohkan dengan konstruktor yang hanya menggunakan argumen String
.
Panggilan konstruktor ini terjadi di dalam metode yang sedang diuji, jadi saya tidak bisa memasukkan ZipFile
yang saya inginkan sebagai parameter.
Misalnya, kodenya terlihat seperti ini:
public void whatever() {
//some code
//some more code
foo();
//yet more unrelated code
}
private Blah foo() {
ZipFile zf;
//a bunch of code we don't care about
zf = new ZipFile(someFile);// I want to give it a known zipfile! mock this!
// some more code we don't care about
Enumeration<?> entries = zf.entries();
ZipEntry entry = (ZipEntry) entries.nextElement();
InputStream is = zf.getInputStream(entry)
//maybe some other calls to the ZipFile
// do something else
}
Pikiran pertama saya adalah melakukan hal berikut dengan ejekan parsial statis:
final ZipFile test = new ZipFile("path/to/actual.zip");
new NonStrictExpectations() {
@Mocked("(java.io.File)")
ZipFile zf;
{
new ZipFile((File) any); result = test;
}
};
Tapi ini tidak akan berfungsi seperti yang ditunjukkan oleh baris ini dalam tutorial: constructors have void return type, so it makes no sense to record return values for them
Pikiran kedua saya adalah mencoba yang berikut ini:
new NonStrictExpectations() {
{
newInstance("java.util.zip.ZipFile", new File("path/to/actual.zip"));
}
};
Tapi ini menimbulkan hal berikut ketika mencoba menginisialisasi file:
java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(Unknown Source)
at java.util.zip.ZipFile.<init>(Unknown Source)
Pikiran ketiga saya adalah menggunakan @MockClass
seperti di bawah ini:
@Before
public void setUp() throws Exception {
Mockit.setUpMocks(MockedZipFile.class);
}
@After
public void tearDown() {
Mockit.tearDownMocks();
}
@MockClass(realClass=ZipFile.class)
public static class MockedZipFile {
public ZipFile it;
@Mock
public void $init(File f) throws ZipException, IOException {
it = new ZipFile("path/to/actual.zip");//this is what would be called
}
}
Tapi ini menghilangkan beberapa tiruan lain yang saya miliki yang memuat file konfigurasi untuk bagian berbeda dari kelas pengujian saya. Belum lagi saya ingin file zip yang berbeda untuk kasus uji yang berbeda.
Saya kira saya bisa mengejek apa saja yang akan dilakukan ZipFile
, tapi ini akan dengan cepat menjadi masalah besar karena disebut di banyak tempat, outputnya perlu diolok-olok, dll, dll. Refactoring untuk mencoba menjadikannya dapat diakses akan terasa canggung, karena kode yang menggunakan ZipFile
bersifat internal pada kode tersebut dan metode publik tidak terlalu mempedulikannya.
Saya merasa ada cara bagi JMockit untuk mengizinkan ini (memberikan contoh tertentu dari suatu objek ketika konstruktor dipanggil), tetapi saya tidak dapat menemukannya. Apakah ada yang punya ide?
EDIT: Saya mencoba metode yang disarankan oleh @Rogerio, tetapi saya mendapat kesalahan baru. Inilah pengaturan saya:
final ZipFile test = new ZipFile("path/to/actual.zip");
new NonStrictExpectations() {
ZipFile zf;
{
zf.entries();
result = test.entries();
zf.getInputStream((ZipEntry) any);
result = new Delegate() {
InputStream getInputStream(ZipEntry entry) throws IOException {
return test.getInputStream(entry);
}
};
}
};
tapi saya mendapatkan jejak tumpukan berikut:
java.lang.InternalError
at path.to.test.ExtractDataTest$1.<init>(ExtractDataTest.java:61)
at path.to.test.ExtractDataTest.setUp(ExtractDataTest.java:61)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
dimana baris 61 adalah baris new NonStrictExpectations() {
.
Saya benar-benar ingin mengatakan "daripada mengejek objek ini, gantikan objek lain yang bertipe sama". Mungkin saya telah mengungkapkannya dengan buruk.
EDIT2: Saya pikir saya harus memasukkan nomor versi: Menggunakan Eclipse 3.6.1 Java 1.6.0_26 JMockit 0.999.10