2013-06-30 23 views
6

Giả sử tôi có chú thích xác thực trên phương thức Giao diện của mình để xác thực đối số đầu vào và giá trị trả về. Có thể tại thời điểm này (V 1.9.5) để yêu cầu Mockito gọi trình xác thực này trong quá trình triệu gọi không?Có thể thêm máy đánh chặn vào tất cả các câu trả lời khi sử dụng Mockito không?

Nền tảng sẽ ngăn không cho các nhà phát triển viết các bài kiểm tra không thực tế bằng cách chế nhạo giao diện đã cho theo cách vi phạm trình xác thực được chỉ định.

Vì vậy, những gì tôi muốn là để đăng ký một cái gì đó giống như

class MyAnswerInterceptor<T> implements AnswerInterceptor<T> { 
    @Override 
    public Answer<T> intercept(final Answer<T> answer) { 
     return new Answer<T>() { 
      @Override 
      public T answer(InvocationOnMock invocation) throws Throwable { 
       validateArguments(invocation); 
       T result = answer.answer(invocation); 
       validateReturnValue(result); 
       return result; 
      } 
     } 
    } 
} 

được kêu gọi tất cả các câu trả lời của một mô hình nhất định. Điều này có thể thực hiện được không? Tôi đã xem xét mã, cũng để kiểm tra xem tôi có thể hack vào một lúc nào đó (thậm chí sử dụng sự phản chiếu hay tương tự), nhưng có vẻ như do sự vướng víu về tạo và tạo logic, khó có thể đạt được những gì tôi muốn (ví dụ công cụ như MockHandler mockHandler = new MockHandlerFactory().create(settings); làm cho nó không thể treo vào và đặt công cụ tùy chỉnh trên đầu mà không cần vá và triển khai toàn bộ sự việc ...)

Bất kỳ cái nhìn sâu sắc sẽ được đánh giá cao :-)

+0

Tìm thấy một giải pháp hoạt động, cụ thể là viết phương thức 'when (T methodCall)' của riêng tôi, bên trong mà tôi ủy quyền cho 'Mockito.when' và sau đó bọc OngoingStubbing vào một proxy Javassist và bắt tất cả' thenBlubb (..) 'phương thức gói câu trả lời tương ứng vào trình chặn của tôi và trả về proxy OngoingStubbing. Dù sao, điều này chắc chắn không phải là cách gọn gàng nhất, vì vậy nếu có ai biết một cách đẹp hơn, tôi vẫn mở để gợi ý ;-) (đặc biệt nó sucks để xử lý tất cả 'sau đóBlubb (..)' phương pháp và nó sẽ yêu cầu thêm chú ý vào từng nâng cấp ...) – pete83

+0

Ngoài ra, giải pháp của bạn sẽ không hoạt động đối với các phương thức như phương pháp void, nơi bạn cần cú pháp doXxx/khi thay cho cú pháp khi/thenXxx. Trừ khi bạn tạo các phiên bản của riêng mình cho từng phương thức doXxx. –

+0

Xin chào! Bạn muốn kết hợp vào các bài kiểm tra đơn vị đơn giản một số logic rất phức tạp. Tại sao không chỉ đơn vị kiểm tra trình xác nhận chính nó một cách riêng biệt từ logic của nơi nó được sử dụng và kiểm tra nó hoàn toàn trong một bài kiểm tra tích hợp? –

Trả lời

2

Bạn có thể đạt được điều đó bằng cách tạo ra một tùy chỉnh MockMaker.

MockMaker là một điểm mở rộng mà làm cho nó có thể sử dụng proxy tùy chỉnh năng động và tránh sử dụng mặc định cglib/asm/objenesis thực hiện

đại biểu thực hiện tùy chỉnh của chúng tôi tất cả những thứ phức tạp để mặc định MockMaker: CglibMockMaker. Nó "trang trí" chỉ bằng phương pháp createMock bằng cách đăng ký tham số settings một InvocationListener. Người nghe này sẽ được thông báo khi một số invocation được thực hiện cho phép sử dụng để gọi validateArgumentsvalidateReturnValue.

import org.mockito.internal.creation.CglibMockMaker; 
import org.mockito.invocation.Invocation; 
import org.mockito.invocation.MockHandler; 
import org.mockito.listeners.InvocationListener; 
import org.mockito.listeners.MethodInvocationReport; 
import org.mockito.mock.MockCreationSettings; 
import org.mockito.plugins.MockMaker; 

public class ValidationMockMaker implements MockMaker { 
    private final MockMaker delegate = new CglibMockMaker(); 

    public ValidationMockMaker() { 
    } 
    @Override 
    public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) { 
     settings.getInvocationListeners().add(new InvocationListener() { 

      @Override 
      public void reportInvocation(MethodInvocationReport methodInvocationReport) { 
       Invocation invocation = (Invocation) methodInvocationReport.getInvocation(); 
       validateArguments(invocation.getArguments()); 
       validateReturnValue(methodInvocationReport.getReturnedValue()); 
      } 
     }); 
     return delegate.createMock(settings, handler); 
    } 

    @Override 
    public MockHandler getHandler(Object mock) { 
     return delegate.getHandler(mock); 
    } 

    @Override 
    public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) { 
     delegate.resetMock(mock, newHandler, settings); 
    } 

    protected void validateArguments(Object... arguments) { 
//  Arrays.stream(arguments).forEach(Objects::requireNonNull); 
    } 

    private void validateReturnValue(Object result) { 
//  Objects.requireNonNull(result); 
    } 
} 

Cuối cùng nhưng không kém, chúng ta cần phải nói đến Mockito sử dụng thực hiện của chúng tôi. Điều này có thể bằng cách thêm một tập tin

mockito-extensions/org.mockito.plugins.MockMaker 

chứa tên lớp MockMaker của chúng tôi:

ValidationMockMaker 

Xem Using the extension point phần trong javadoc.

+0

Tuyệt vời, trông chính xác như điều tôi cần, cảm ơn rất nhiều !!! Tôi sẽ thử phương pháp đó càng sớm càng tốt :-) – pete83

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