2014-12-27 18 views
16

Tôi là một fan hâm mộ lớn của Mockito, không may cho one of my projects trong đó sử dụng Java 8, nó không thành công vào tôi ...Bạn có thể làm cho mockito (1.10.17) hoạt động với các phương thức mặc định trong giao diện không?

Kịch bản:

public final class MockTest 
{ 
    @Test 
    public void testDefaultMethodsWithMocks() 
    { 
     final Foo foo = mock(Foo.class); 

     //when(foo.bar()).thenCallRealMethod(); 

     assertThat(foo.bar()).isEqualTo(42); 
    } 

    @FunctionalInterface 
    private interface Foo 
    { 
     int foo(); 

     default int bar() 
     { 
      return 42; 
     } 
    } 
} 

Thật không may, thử nghiệm thất bại và foo.bar() lợi nhuận 0.

Khi tôi bỏ ghi chú dòng when(), tôi nhận được một vết đống ...

java.lang.NoSuchMethodError: java.lang.Object.bar()I 
    at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18) 

Đây là phiên bản ổn định mới nhất hiện có trên maven; googling xung quanh đã không cho tôi biết nhiều về tình trạng của mockito liên quan đến chức năng mới này trong Java 8 ...

Bạn có thể làm cho nó hoạt động theo cách khác hơn là triển khai giao diện và spy() trên chúng (công trình này)?

+0

tôi nghi ngờ rằng đây là kết quả của cách mà Mockito xử lý thế hệ proxy năng động cho mocks và sẽ cần một bản cập nhật cho cơ sở hạ tầng. Bạn đã kiểm tra liệu có một vấn đề nổi bật chống lại Mockito cho nó? – chrylis

+0

@chrylis no, không phải cho điểm này nói riêng; có một vấn đề được mở ra liên quan đến Java 8 và các phương thức mặc định, và trình phát vấn đề được nói đúng (tôi ngu ngốc không nghĩ về điều này lúc đầu) rằng anh ta phải biên dịch mockito với Java 8 để làm việc thử nghiệm. Có vẻ ảm đạm:/ – fge

+0

Vâng. Vẫn còn một vài thư viện ở đó duy trì dĩa cho 1.4. – chrylis

Trả lời

10

Với Mockito 2.x, JDK 8 phương pháp mặc định là hỗ trợ.

Với Mockito 1.xkhông thể,


Cũ câu trả lời

Đáng tiếc là nó chưa thể (Mockito 1.10.19), từ README.md trên github 'trang

Trạng thái JDK8

Mockito sẽ hoạt động tốt với JDK8 nếu bạn tránh xa các phương pháp mặc định (còn gọi là phương pháp hậu vệ). Việc sử dụng Lambda có thể hoạt động tốt cho các câu trả lời. Chúng tôi không chắc chắn về mọi tính năng của JDK8 vào lúc này, giống như việc tuần tự hóa một mô hình sử dụng lambda. Báo cáo lỗi và yêu cầu kéo được chào đón mặc dù (hướng dẫn đóng góp).

EDIT 1: phương pháp hậu vệphương pháp mặc định là tên gọi khác nhau cho cùng một điều.

Tôi hy vọng cho một sự thay thế mockmaker mà sẽ xử lý java 8 opcodes đúng đối với trường hợp như một số opcodes có ngữ nghĩa khác nhau trong Java 8.

EDIT 2: Cập nhật các readme Mockito, và trích dẫn này phù hợp

+0

Uh, vâng, tôi thấy điều đó, nhưng tôi tự hỏi liệu "phương pháp hậu vệ" thực sự có nghĩa là các phương thức mặc định trong giao diện; và phương pháp "hậu vệ" là gì? – fge

+2

có nó chỉ là một tên khác cho _default methods_ – Brice

+1

Vâng, OK, sau đó, tôi đoán tôi sẽ gửi yêu cầu kéo để cập nhật README ... Tôi không tin rằng nhiều người biết rằng hai từ này là từ đồng nghĩa – fge

3

Tôi vừa thử Mockito 2.0.38-beta và đã hoạt động trong phiên bản đó. Nhưng Mockito phải được thông báo rõ ràng để gọi triển khai mặc định.

Foo foo = mock(Foo.class); 
assertThat(foo.bar()).isEqualTo(0); 

when(foo.bar()).thenCallRealMethod(); 
assertThat(foo.bar()).isEqualTo(42); 
1

Bạn có thể vượt qua giới hạn này bằng cách triển khai giao diện (được thử nghiệm trong Mockito 1.10.19):

public class TestClass { 
    @Mock ImplementsIntWithDefaultMethods someObject; 


    @Test public void test() throws Exception { 
    // calling default method on mocked subtype works 
    someObject.callDefaultMethod(); 
    } 


    /* Type that implements the interface */ 
    static class ImplementsIntWithDefaultMethods implements IntWithDefaultMethod { } 

    /* Interface you need mocked */ 
    interface IntWithDefaultMethod { 
    default void callDefaultMethod { } 
    } 
} 
0

Tôi vừa gặp vấn đề tương tự với Mockito (org.mockito: mockito-core: 1.10.19). Vấn đề là: Tôi không thể thay đổi phiên bản Mockito (2.7.22 sẽ hoạt động) vì phụ thuộc vào org.springframework.boot: spring-boot-starter-test: 1.4.3.RELEASE mà chúng tôi đang sử dụng (Spring, Mockito issue) .

Giải pháp đơn giản nhất mà tôi tìm thấy là triển khai giao diện với lớp trừu tượng riêng trong lớp thử nghiệm của tôi và chế nhạo cái đó (cũng so sánh với giải pháp của @Mihai Bojin). Làm như thế này sẽ giúp bạn tránh khỏi những rắc rối cũng để "thực hiện" tất cả các phương thức được yêu cầu bởi (các) giao diện.

MWe:

public interface InterfaceWithDefaults implements SomeOtherInterface { 
    default int someConstantWithoutSense() { 
     return 11; 
    } 
} 

public class SomeTest { 
    private abstract class Dummy implements InterfaceWithDefaults {} 

    @Test 
    public void testConstant() { 
     InterfaceWithDefaults iwd = Mockito.mock(Dummy.class); 

     Assert.assertEquals(11, iwd.someConstantWithoutSense()); 
    } 
} 
Các vấn đề liên quan