2013-01-09 6 views
5

Tôi đang cố gắng giả lập lớp J232I Query với mockito, tuy nhiên nó không mô phỏng các phương thức của lớp cơ sở SqlStatement.các sự cố chế nhạo một lớp

Khi chạy mã bên dưới câu lệnh khi thực sự gọi triển khai cụ thể trong lớp cơ sở và không thành công với NullPointerException.

import java.util.Map; 

import org.junit.Test; 
import org.skife.jdbi.v2.Query; 

import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.when; 

public class TestClass { 
    @Test 
    public void testBind() { 
     Query<Map<String,Object>> mockQuery = mock(Query.class); 
     when(mockQuery.bind("xxx", 5)).thenReturn(mockQuery); //this line fails 
     //more stuff here 
    } 
} 

Tôi cũng đã thử điều này với EasyMock và nhận được kết quả tương tự, không thể giả lập phương pháp này.

More Info:

  • phiên bản Mockito là 1.9.5 phiên bản
  • JDBI là 2.4.1 (một trong đó hiện tàu với dropwizard)

Trường hợp ngoại lệ là:

java.lang.NullPointerException 
     at org.skife.jdbi.v2.SQLStatement.bind(SQLStatement.java:434) 
     at TestClass.testBind(TestClass.java:17) 
      at .... 

Bất kỳ ý tưởng nào về cách giải quyết vấn đề này?

+0

Đây không phải là câu trả lời, nhưng trong kinh nghiệm của tôi chế nhạo loại mã DAO này là một sự lãng phí thời gian. Nó sẽ không phơi bày các lỗi bạn thực hiện khi sử dụng API JDBI. Viết các bài kiểm tra dựa vào cơ sở dữ liệu thực. – artbristol

Trả lời

4

bind phương pháp trong SqlStatement là cuối cùng (ví dụ SQLStatement#bind(String, int)), do đó bạn không thể nhạo báng họ sử dụng Mockito, đó là một hạn chế của JVM (EDIT :) Mockito rằng không thể bỏ qua tại chốc lát.


EDIT2: Lưu ý rằng như các ý kiến ​​dưới điểm ra, có một số hiểu lầm về những gì được viết ở trên, và điều này đòi hỏi phải làm rõ về một phần của tôi:

  • Hạn chế của JVM có nghĩa là bạn không thể nạp một lớp con của một kiểu được gắn cờ với một truy cập cuối cùng, bạn không thể ghi đè lên một phương thức được gắn cờ với truy cập cuối cùng, nếu không bạn sẽ nhận được một VerifyError. §8.1.1.2 final classes of the Java Language Specification§8.4.3.3 final methods of the JLS§4.10 of the Java Virtual Machine Specification
  • rằng Mockito không thể bỏ qua nghĩa Mockito hiện chưa thể vượt qua các lớp học chính thức hoặc các phương pháp cuối cùng để nhạo báng họ, bởi vì tại thời điểm sử dụng Mockito cglib để tạo ra các lớp con của các loại để chế nhạo. Nhưng các khung công tác khác (như PowerMock hoặc JMockit) có thể thực hiện được vì chúng có các chiến lược khác để khắc phục điều này.

lựa chọn của bạn là để thay đổi thiết kế của bạn, do đó bạn sẽ không phải còn sơ khai những tương tác, hoặc bạn phải sử dụng PowerMock trong đó sử dụng phức tạp thủ đoạn với classloaders để viết lại lớp bytecode (không tiếp cận ưa thích của tôi, mặc dù PowerMock kỹ thuật ấn tượng).

Hy vọng điều đó sẽ hữu ích.

+1

Đó là một hạn chế của Mockito, không phải của JVM, như ngụ ý bởi nhận xét của riêng bạn rằng PowerMock hỗ trợ nó. Chưa kể rằng JMockit * cũng * hỗ trợ nó, mặc dù nó không "sử dụng các thủ thuật phức tạp với các trình nạp lớp". –

+0

@Rogerio Xem bản chỉnh sửa: "mà mockito không thể bỏ qua tại thời điểm" – Brice

+1

Tôi đã thấy nó. Nó vẫn không phải là giới hạn của JVM, ngay cả tài liệu chính thức của Mockito [nói] (http://code.google.com/p/mockito/wiki/FAQ). (Nhưng tôi lặp lại chính mình ...) Nếu có một mục tiêu để "bỏ qua nó", tôi sẽ đề nghị kết hợp mã từ PowerMockito (tức là, bằng cách sử dụng một trình nạp lớp tùy chỉnh). Lựa chọn duy nhất khác là sử dụng cách tiếp cận của JMockit, với việc sử dụng 'java.lang.instrument'. –

0

Hãy thử

Mockito.doReturn(mockQuery).when(mockQuery).bind("xxx",5); 
+0

lỗi tương tự, vẫn gọi phương thức lớp cơ sở – LiorH

+0

Bạn có thể đăng ngoại lệ và phiên bản Mockito bạn đang sử dụng hay không. Tôi vừa chạy cả hai cách thành công với Mockito 1.9.0 và jdbi 2.9.4 – bstick12

+0

thông tin được thêm vào – LiorH