2013-04-11 27 views
18

Tôi không chắc chắn về cách chế tạo một lớp enum singleton.Làm thế nào để thử một lớp singum enum sử dụng Mockito/Powermock?

public enum SingletonObject{ 
    INSTANCE; 
    private int num; 

    protected setNum(int num) { 
    this.num = num; 
    } 

    public int getNum() { 
    return num; 
    } 

Tôi muốn khai báo getNum() trong ví dụ trên, nhưng tôi không thể tìm ra cách giả lập lớp SingletonObject thực tế. Tôi đã nghĩ rằng việc sử dụng Powermock để chuẩn bị cho bài kiểm tra sẽ giúp ích bởi vì enums vốn đã là cuối cùng.

//... rest of test code 
@Test 
public void test() { 
    PowerMockito.mock(SingletonObject.class); 
    when(SingletonObject.INSTANCE.getNum()).thenReturn(1); //does not work 
} 

Điều này đang sử dụng PowerMockMockito 1.4.10 và Mockito 1.8.5.

+0

Kiểm tra chủ đề tương tự: http://stackoverflow.com/questions/2302179/mocking-a-singleton-class –

+0

Cảm ơn Martin, tôi đã đọc qua chủ đề đó và có vẻ như đó là cách tiếp cận để sử dụng cách không tích cực của thực hiện một singleton, và tôi có thể sử dụng chế nhạo đúng cách với phương pháp đó. Tuy nhiên, có cách nào để thử một lớp enum singleton? Từ những gì tôi đã thu thập, enum singleton class là phương pháp được khuyến cáo để khai báo một singleton sau java 1.5. –

+0

[Re: PowerMock: tôi có thể giả lập enums không?] (Https://groups.google.com/forum/?fromgroups=#!topic/powermock/hqrJaMi0Zrc) – Joe

Trả lời

23

Nếu bạn muốn loại bỏ những gì INSTANCE trả về, bạn có thể làm điều đó nhưng nó khá khó chịu (sử dụng thao tác bytecode phản chiếu &). Tôi đã tạo & thử nghiệm một dự án đơn giản với ba lớp học bằng PowerMock 1.4.12/Mockito 1.9.0. Tất cả các lớp học đều nằm trong cùng một gói.

SingletonObject.java

public enum SingletonObject { 
    INSTANCE; 
    private int num; 

    protected void setNum(int num) { 
     this.num = num; 
    } 

    public int getNum() { 
     return num; 
    } 
} 

SingletonConsumer.java

public class SingletonConsumer { 
    public String consumeSingletonObject() { 
     return String.valueOf(SingletonObject.INSTANCE.getNum()); 
    } 
} 

SingletonConsumerTest.java

import static org.junit.Assert.*; 
import static org.powermock.api.mockito.PowerMockito.*; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 
import org.powermock.reflect.Whitebox; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({SingletonObject.class}) 
public class SingletonConsumerTest { 
    @Test 
    public void testConsumeSingletonObject() throws Exception { 
     SingletonObject mockInstance = mock(SingletonObject.class); 
     Whitebox.setInternalState(SingletonObject.class, "INSTANCE", mockInstance); 

     when(mockInstance.getNum()).thenReturn(42); 

     assertEquals("42", new SingletonConsumer().consumeSingletonObject()); 
    } 
} 

Các cuộc gọi đến Whitebox.setInternalState thay thế INSTANCE với một đối tượng giả mà bạn có thể thao tác trong vòng Bài kiểm tra của bạn.

+1

Nhưng làm thế nào bạn có thể thử SingletonObject. lớp học? Nó sẽ cung cấp cho MockitoException với bình luận "Mockito không thể giả/gián điệp sau đây: - lớp cuối cùng - lớp ẩn danh - kiểu nguyên thủy" – Thamiar

+1

Điều này sử dụng PowerMock. –

+0

Xin chào, tôi đã nhận được 'java.lang.IllegalAccessException: Không thể đặt cuối cùng tĩnh' trong khi sử dụng' Whitebox.setInternalState'. Bạn có biết tại sao? – elsennov

Các vấn đề liên quan