Java 是否可以使用PowerMock来模拟新文件的创建?

Java 是否可以使用PowerMock来模拟新文件的创建?,java,powermock,Java,Powermock,我想介绍一种逻辑,它使用单元测试创建文件。可以模拟文件类并避免实际的文件创建吗?我不确定这是否可行,但我有这样的要求,我通过创建文件服务接口解决了这个问题。因此,您没有直接创建/访问文件,而是添加了一个抽象。然后,您可以在测试中轻松地模拟此接口 例如: public interface FileService { InputStream openFile(String path); OutputStream createFile(String path); } 然后在你的课

我想介绍一种逻辑,它使用单元测试创建文件。可以模拟文件类并避免实际的文件创建吗?

我不确定这是否可行,但我有这样的要求,我通过创建
文件服务
接口解决了这个问题。因此,您没有直接创建/访问文件,而是添加了一个抽象。然后,您可以在测试中轻松地模拟此接口

例如:

public interface FileService {

    InputStream openFile(String path);
    OutputStream createFile(String path);

}
然后在你的课堂上使用这个:

public class MyClass {

    private FileService fileService;

    public MyClass(FileService fileService) {
        this.fileService = fileService;
    }

    public void doSomething() {
        // Instead of creating file, use file service
        OutputStream out = fileService.createFile(myFileName);
    }
}
在你的测试中

@Test
public void testOperationThatCreatesFile() {
    MyClass myClass = new MyClass(mockFileService);
    // Do your tests
}

这样,您甚至可以在没有任何模拟库的情况下模拟它。

模拟构造函数,如下面的示例代码所示不要忘记将调用“新文件(…)”的类放入@PrepareForTest

package hello.easymock.constructor;

import java.io.File;

import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({File.class})
public class ConstructorExampleTest {

    @Test
    public void testMockFile() throws Exception {

        // first, create a mock for File
        final File fileMock = EasyMock.createMock(File.class);
        EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path");
        EasyMock.replay(fileMock);

        // then return the mocked object if the constructor is invoked
        Class<?>[] parameterTypes = new Class[] { String.class };
        PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock);
        PowerMock.replay(File.class); 

        // try constructing a real File and check if the mock kicked in
        final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath();
        Assert.assertEquals("/my/fake/file/path", mockedFilePath);
    }

}
包hello.easymock.constructor;
导入java.io.File;
导入org.easymock.easymock;
导入org.junit.Assert;
导入org.junit.Test;
导入org.junit.runner.RunWith;
导入org.powermock.api.easymock.powermock;
导入org.powermock.core.classloader.annotations.PrepareForTest;
导入org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest({File.class})
公共类构造函数示例测试{
@试验
public void testMockFile()引发异常{
//首先,为文件创建一个mock
最终文件fileMock=EasyMock.createMock(File.class);
expect(fileMock.getAbsolutePath()).andReturn(“/my/fake/file/path”);
EasyMock.replay(fileMock);
//然后,如果调用了构造函数,则返回模拟对象
类[]参数类型=新类[]{String.Class};
expectNew(File.class,parameterTypes,EasyMock.isA(String.class)).andReturn(fileMock);
replay(File.class);
//尝试构建一个真实的文件,并检查模拟是否启动
最后一个字符串mockedFilePath=新文件(“/real/path/for/File”).getAbsolutePath();
Assert.assertEquals(“/my/fake/file/path”,mockedFilePath);
}
}
试试PowerMockito

import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;


@PrepareForTest(YourUtilityClassWhereFileIsCreated.class)
public class TestClass {

 @Test
 public void myTestMethod() {
   File myFile = PowerMockito.mock(File.class);
   PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(myFile);
   Mockito.when(myFile.createNewFile()).thenReturn(true);
 }

}

这是一个好问题。不值得被否决。你用PowerMock试过吗?PowerMock在方法内部模拟新对象创建,因此应该可以工作。正确。当你不能模拟时,把它包装在一个抽象(接口)中,然后模拟它。但是当你改变真正的代码来帮助测试时,用EasyMock避免这种情况是很好的,也是可能的/PowerMock@CarlosHenriqueRodriguez是的,你是。这是件好事。编写可测试(通常)的代码可以减少代码中的耦合。您应该将测试代码视为架构的一部分,但即使是松耦合的代码也需要比这更强大的功能。例如,如果您需要测试FileServiceImpl行为,那么无论如何都需要模拟文件构造函数。但是,在这个级别,我会考虑用集成测试来验证它,就像我对一个进行数据库操作的类所做的那样。毕竟,即使没有模拟,创建和/或验证文件也是非常简单的。