2012-08-06 24 views
5

Tôi hiện đang làm việc trên một số công cụ giám sát bằng cách sử dụng aspectj. Bởi vì công cụ này nên là công nghệ độc lập (càng nhiều càng tốt), tôi không sử dụng Spring để tiêm. Nhưng tôi muốn các khía cạnh của tôi được kiểm tra đơn vị.Làm thế nào để thử một khía cạnh

Aspect dụ:

@Aspect 
public class ClassLoadAspect { 
    private Repository repository; 

    public ClassLoadAspect() { 
     repository = OwlApiRepository.getInstance(); 
    } 

    @After("anyStaticInitialization()") 
    public void processStaticInitilization(JoinPoint jp) { 
     Class type = jp.getSourceLocation().getWithinType(); 
     if (type.isInterface()) { 
      repository.storeInterfaceInitialization(type); 
     } else if (type.isEnum()) { 
      repository.storeEnumInitialization(type); 
     } else { 
      repository.storeClassInitialization(type); 
     } 

    } 

    @Pointcut("staticinitialization(*) && !within(cz.cvut.kbss.odra..*)") 
    public void anyStaticInitialization() { 
    } 

    public Repository getRepository() { 
     return repository; 
    } 

    public void setRepository(Repository repository) { 
     this.repository = repository; 
    } 
} 

Tuy nhiên, tôi thực sự không biết, làm thế nào để xây dựng thử nghiệm đơn vị (các lĩnh vực kho nên được chế giễu (sử dụng Mockito)), Nhưng tôi không có sự sáng tạo khía cạnh dưới sự kiểm soát, do đó Tôi không thể đặt phụ thuộc theo cách thủ công. Tôi nên gọi gì để nhận được cá thể? Hoặc có một số kịch bản khác như thế nào để kiểm tra đơn vị khía cạnh khía cạnh.

Cảm ơn.

Trả lời

2

Bạn nói rằng bạn tìm cách riêng của bạn giới thiệu các đối tượng giả hacky. Chính xác những gì bạn không thích và làm thế nào để bạn tưởng tượng nó được? Tôi chỉ có thể đoán:

Bạn không thích thực tế là bạn thay thế toàn cầu các cuộc gọi đến OwlApiRepository.getInstance() trong khía cạnh meta của mình? Sau đó, bạn đặc biệt có thể hạn chế tiêm đối tượng giả đến constructor của khía cạnh (Tôi đang sử dụng cú pháp AspectJ mẹ đẻ vì tôi cảm thấy không thoải mái với POJO phong cách chú thích):

public privileged aspect ClassLoadTestAspect { 
    static boolean active = true; 

    declare precedence : ClassLoadTestAspect, ClassLoadAspect; 
    pointcut classLoadAspect() : 
     if(active) && 
     withincode(ClassLoadAspect.new()) && 
     call(* OwlApiRepository.getInstance()); 

    Object around() : classLoadAspect() { 
     return new MockRepository(); 
    } 
} 

Như bạn cũng có thể thấy, biến thể này của một meta (khía cạnh -testing) cũng có một công tắc để bật và tắt tùy ý. Có lẽ đây cũng là thứ bạn không thích. Như tôi đã nói, tôi đoán vậy. Sau phản hồi của bạn, tôi có thể trả lời cụ thể hơn.

Edit: Đối với mối quan tâm của bạn, tôi nghĩ rằng tôi đã giải quyết chúng càng nhiều càng tốt:

  • Bạn không cần một người giữ giả.

  • Khía cạnh có thể được (de) được kích hoạt. Nó sẽ dễ dàng để làm cho kích hoạt của nó phụ thuộc vào các điều kiện khác, vì vậy nó chỉ hoạt động trong môi trường thử nghiệm của bạn. Nếu điều này vẫn chưa đủ, hãy sử dụng thời gian biên dịch cho các khía cạnh sản xuất của bạn và thời gian tải dệt cho khía cạnh thử nghiệm của bạn. Bằng cách này, mã byte của nó sẽ không có mặt trong môi trường sản xuất của bạn.

  • Phiên bản của tôi không thay thế toàn cục, nhưng giống như một bác sĩ phẫu thuật tốt chỉ cắt giảm một cách xâm lấn tối thiểu chính xác tại một nơi.

  • Tôi thực sự không thể hiểu được mối lo ngại của bạn về thao tác mã byte vì nhiều lý do: Bạn sử dụng AspectJ, tức là thao tác mã byte vốn (dệt). Bạn sử dụng Mockito để tạo các lớp khi chạy. Tôi cũng không hiểu nơi bạn thấy sự thiếu hụt trong AspectJ. Bạn chưa giải thích cách bạn muốn "phương tiện chuẩn của ngôn ngữ" hoạt động hoặc giao diện nào cần cung cấp để thử nghiệm. Ngay cả khi bạn đã có, tôi không thể thay đổi ngôn ngữ (AJ) và công cụ (Mockito) của sự lựa chọn của riêng bạn cho bạn.

+0

Điều tôi không thích trong giải pháp của mình: thay thế toàn bộ phương pháp tĩnh khó kiểm tra - tôi phải đặt lại kho lưu trữ theo cách thủ công (thay vì đặt mô hình mới). Tôi cũng phải tạo ra một người giữ giả để truy cập vào đối tượng kho lưu trữ giả. Điều thứ ba là tôi không thích ôn hòa với bytecode để thiết lập mô hình, tôi thực sự nghĩ rằng điều này phải được thực hiện bằng các phương tiện chuẩn của ngôn ngữ (nếu nó không thể, nó cho thấy sự thiếu hụt trong aspectj thiết kế). Nhưng từ mã, giải pháp của bạn có thể làm (ít nhất là không cần chủ) :-). – malejpavouk

+0

Điểm được lấy, tiền thưởng là của bạn. Cảm ơn :-) – malejpavouk

+0

Xin lỗi vì tiếng ồn. Tôi đã quyết định thêm nhận xét vào câu trả lời của mình vì số lượng ký tự có sẵn cho nhận xét quá nhỏ. Nhưng cảm ơn dù sao để trao cho tôi tiền thưởng. :) – kriegaex

1

bạn có thể chia các thử nghiệm của mình. đầu tiên kiểm tra logic của khía cạnh. đó là một bài thơ. bạn có thể kiểm tra nó theo cách bạn muốn. phần thứ hai là kiểm tra các phím tắt. trong trường hợp này tạo ra một khía cạnh đơn giản khác với cùng một điểm đánh dấu (ví dụ: trích xuất chúng dưới dạng hằng số). có lẽ có một số công cụ kiểm tra chuyên dụng nhưng tôi không biết về bất kỳ và đó là cách đơn giản nhất mà tôi suy nghĩ của tôi

1

giải pháp hiện tại của tôi đang giới thiệu AspectJ này hack để ghi đè lên các phương pháp nhà máy độc thân

@Aspect 
public class MockingAspect { 

    @Around("call(synchronized static OwlApiRepository *(..))") 
    public OwlApiRepository processGetInstance(ProceedingJoinPoint jp) {  
     System.out.println("getting mock"); 
     return MockHolder.getMock(); 
    } 
} 
0

Làm thế nào về một cái gì đó dọc theo những dòng này, về cơ bản tiếp tục giữ cho khía cạnh của bạn, bên trong giao diện hành vi cho giao diện khác, và giả lập giao diện cho các bài kiểm tra của bạn, thay vì chế giễu các khía cạnh chính nó. Đây là một giả:

public interface ClassLoadHelper{ 
    void processStaticInitialization(Class<?> clazz); 
} 

public class ClassLoadHelperImpl implements ClassLoadHelper{ 
    private Repository repository; 

    public ClassLoadHelperImpl() { 
     repository = OwlApiRepository.getInstance(); 
    } 

    void processStaticInitialization(Class<?> clazz){ 
     if (type.isInterface()) { 
      this.repository.storeInterfaceInitialization(type); 
     } else if (type.isEnum()) { 
      this.repository.storeEnumInitialization(type); 
     } else { 
      this.repository.storeClassInitialization(type); 
     }   
    } 
} 


@Aspect 
public class ClassLoadAspect { 
    private ClassLoadHelper classLoadHelper; 


    @After("anyStaticInitialization()") 
    public void processStaticInitilization(JoinPoint jp) { 
     Class<?> type = jp.getSourceLocation().getWithinType(); 
     this.classLoadHelper.processStaticInitialization(type); 

    } 

    @Pointcut("staticinitialization(*) && !within(cz.cvut.kbss.odra..*)") 
    public void anyStaticInitialization() { 
    } 

    public ClassLoadHelper getClassLoadHelper() { 
     return classLoadHelper; 
    } 

    public void setClassLoadHelper(ClassLoadHelper classLoadHelper) { 
     this.classLoadHelper = classLoadHelper; 
    } 
} 

Bây giờ trong thử nghiệm của bạn, bạn có thể làm điều này:

ClassLoadAspect.aspectOf().setClassLoadHelper(mockClassLoadHelper); 
1

Bạn chỉ muốn kiểm tra đơn vị đúng không? Đây là một thử nghiệm đơn vị nhỏ để thử nghiệm chú thích tùy chỉnh với các khía cạnh với mục đích bao bọc một sự ném trong một ngoại lệ ứng dụng tùy chỉnh. (Testng + Mockito)

public class ResourceApplicationExceptionAspectTest { 
@Mock 
private ProceedingJoinPoint pjp; 
@Mock 
private ResourceApplicationException resourceApplicationException; //annotation definition 

@BeforeMethod 
public void setUp() throws Exception { 
    MockitoAnnotations.initMocks(this); 

} 

@Test(groups ="unit", expectedExceptions = ResourceApplicationException.class) 
public void testWrapExceptionAdvice() throws Throwable { 

    ResourceApplicationExceptionAspect aspect = new ResourceApplicationExceptionAspect(); 

    when(pjp.proceed()).thenThrow(new NullPointerException()); 
    aspect.wrapExceptionAdvice(pjp, resourceApplicationException); 
} 
Các vấn đề liên quan