I considered the following question, and this is not the same as mine:
jMockit: how to expect constructor calls for mocked objects?
This question is similar, but the answer does not help me:
How to make fun of the default constructor of the Date class using JMockit?
I am trying to make moker call the constructor java.util.zip.ZipFile , especially the one that has the java.io.File argument. I would like the constructor to return an instance of another ZipFile , which I will create using a constructor that takes only the String argument.
This constructor call occurs inside the test method, so I cannot insert a ZipFile as a parameter.
For example, the code looks something like this:
public void whatever() {
My first thought was to do the following with static partial mockery:
final ZipFile test = new ZipFile("path/to/actual.zip"); new NonStrictExpectations() { @Mocked("(java.io.File)") ZipFile zf; { new ZipFile((File) any); result = test; } };
But this will not work, as indicated in this line in the tutorial: constructors have void return type, so it makes no sense to record return values for them
My second thought was to try the following:
new NonStrictExpectations() { { newInstance("java.util.zip.ZipFile", new File("path/to/actual.zip")); } };
But when you try to initialize the file, this causes the following:
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)
My third thought was to use @MockClass as shown below:
@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");
But these are the hoses for some other layouts that I have, loading the configuration file for another part of my test class. Not to mention that I need different zip files for different test cases.
I suppose I could make fun of everything ZipFile , but it would quickly become a huge pain, because it was called a lot of places, the output would be a mockery, etc. etc. Refactoring to try to make it accessible will be inconvenient, since the code that uses ZipFile is internal to the code, and public methods really don't care about that.
I have a feeling that JMockit allows this to be resolved (by giving a specific instance of the object when the constructor is called), but I cannot figure it out. Does anyone have any ideas?
EDIT: I tried the method suggested by @Rogerio, but I have a new error. Here is my setup:
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); } }; } };
but I get the following stack trace:
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)
where line 61 is the line new NonStrictExpectations() { .
I really want to say, "instead of mocking this object, replace this other object of the same type." Maybe I said it badly.
EDIT2: I figured it should include version numbers: Using Eclipse 3.6.1 Java 1.6.0_26 JMockit 0.999.10