2013-04-16 54 views
7

Tôi muốn bao gồm một logic, tạo tệp với các bài kiểm tra đơn vị. Có thể giả lập lớp Tệp và để tránh tạo tệp thực tế không?Có thể sử dụng PowerMock để thử tạo tệp mới không?

+0

Đây là một câu hỏi hay. Không xứng đáng được giảm giá. –

+0

Bạn đã thử sử dụng PowerMock chưa? PowerMock không mô phỏng các sáng tạo đối tượng mới bên trong phương thức nên hoạt động. –

Trả lời

6

Giả lập hàm tạo, như trong mã ví dụ này. Đừng quên để đặt lớp mà sẽ gọi "File mới (...)" trong @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); 
    } 

} 
6

Tôi không chắc chắn nếu nó có thể, nhưng tôi đã có một yêu cầu như vậy, và tôi đã giải quyết nó bằng cách tạo ra một giao diện FileService. Vì vậy, thay vì tạo/truy cập tập tin trực tiếp, bạn thêm một trừu tượng. Sau đó, bạn có thể dễ dàng thử giao diện này trong các bài kiểm tra của bạn.

Ví dụ:

public interface FileService { 

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

} 

Sau đó, trong lớp học của bạn sử dụng này:

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); 
    } 
} 

Và trong thử nghiệm của bạn

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

Bằng cách này, bạn thậm chí có thể thử nó mà không có bất kỳ giả thư viện.

+0

Chính xác. Khi bạn không thể giả lập, hãy bọc nó trong một giao diện trừu tượng và sau đó giả lập nó. –

+0

Nhưng sau đó bạn đang thay đổi mã thực sự để giúp các bài kiểm tra, nó là tốt và có thể để tránh điều này với EasyMock/PowerMock – cahen

+0

@CarlosHenriqueRodriguez Có, bạn đang có. Và đó là một điều tốt. Viết mã có thể kiểm tra (thường) làm giảm khớp nối trong mã của bạn. Bạn nên xem xét mã thử nghiệm là một phần của kiến ​​trúc của bạn. – NilsH

4

thử 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); 
} 

}