我看过以下问题,它与我的不同:
这个问题很相似,但答案对我没有帮助:
如何使用 JMockit 模拟 Date 类的默认构造函数?
我想做的是模拟对 的构造函数调用java.util.zip.ZipFile
,特别是有java.io.File
参数的调用。我希望构造函数返回一个不同的实例ZipFile
,我将使用只接受一个String
参数的构造函数进行实例化。
这个构造函数调用发生在被测方法中,所以我不能注入ZipFile
我想要的作为参数。
例如,代码如下所示:
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
}
我的第一个想法是使用静态部分模拟执行以下操作:
final ZipFile test = new ZipFile("path/to/actual.zip");
new NonStrictExpectations() {
@Mocked("(java.io.File)")
ZipFile zf;
{
new ZipFile((File) any); result = test;
}
};
但这不会像教程中的这一行所示那样工作:constructors have void return type, so it makes no sense to record return values for them
我的第二个想法是尝试以下方法:
new NonStrictExpectations() {
{
newInstance("java.util.zip.ZipFile", new File("path/to/actual.zip"));
}
};
但这在尝试初始化文件时会引发以下情况:
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)
我的第三个想法是使用@MockClass
如下:
@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
}
}
但是这个软管我有一些其他的模拟,它们为我的测试类的不同部分加载配置文件。更不用说我会为不同的测试用例需要不同的 zip 文件。
我想我可以嘲笑一切会做的ZipFile
事情,但这很快就会变成一个巨大的痛苦,因为它被称为很多地方,它的输出需要被嘲笑等等。重构试图使其易于访问会很尴尬,因为使用 的代码ZipFile
是代码内部的,公共方法并不真正关心它。
我有一种感觉 JMockit 有一种方法允许这样做(在调用构造函数时给出对象的特定实例),但我无法弄清楚。有没有人有任何想法?
编辑:我尝试了@Rogerio 建议的方法,但出现了一个新错误。这是我的设置:
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);
}
};
}
};
但我得到以下堆栈跟踪:
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)
其中第 61 行是该new NonStrictExpectations() {
行。
我真的想说“与其模拟这个对象,不如替换这个相同类型的另一个对象”。也许我表达得不好。
EDIT2:我想我应该包括版本号:Using Eclipse 3.6.1 Java 1.6.0_26 JMockit 0.999.10