2010-07-19 30 views
6

Tôi đang cố gắng viết một bài kiểm tra JUnit cho một dự án Spring Roo. Nếu thử nghiệm của tôi yêu cầu sử dụng các lớp thực thể, tôi nhận được Ngoại lệ sau:Làm cách nào để sử dụng các thử nghiệm JUnit với Spring Roo? (Các vấn đề với EntityManager)

java.lang.IllegalStateException: Entity manager has not been injected 
(is the Spring Aspects JAR configured as an AJC/AJDT aspects library?) 

Khía cạnh Spring JAR trông được định cấu hình chính xác. Đặc biệt, anh có chữ sau đây trong tập tin pom.xml:

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-aspects</artifactId> 
    <version>${spring.version}</version> 
</dependency> 

<plugin> 
    <configuration> 
    <outxml>true</outxml> 
    <aspectLibraries> 
    <aspectLibrary> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-aspects</artifactId> 
    </aspectLibrary> 
    </aspectLibraries> 
    <source>1.6</source> 
    <target>1.6</target> 
    </configuration> 
</plugin> 

và các lớp có sử dụng các lớp thực thể hoạt động tốt, khi không được gọi từ một thử nghiệm JUnit. Bất kỳ ý tưởng làm thế nào tôi có thể thiết lập những thứ lên để quản lý thực thể được tiêm từ một bài kiểm tra JUnit?

Đây là tôi class Test (nhiều hơn hoặc ít hơn):

public class ServiceExampleTest { 

    @Test 
    public void testFoo() { 
    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
    } 
} 

này là đủ để ném ngoại lệ. Lớp FooServiceImpl trả về một tập hợp các Foo, trong đó Foo là một lớp thực thể. Phương thức getFoos() hoạt động khi ứng dụng được chạy theo cách thông thường. Vấn đề chỉ xuất hiện trong bối cảnh kiểm tra đơn vị.

+0

Bạn có thể đăng lớp thử nghiệm của bạn không? Tôi chưa bao giờ sử dụng Spring Roo, nhưng với các bài kiểm tra Spring bình thường, bạn thường phải mở rộng AbstractSpringJUnit4Test (hoặc một cái gì đó) hoặc sử dụng một Runner Spring tùy chỉnh thông qua chú thích cho các bài kiểm tra. – ponzao

Trả lời

3

Đây là một vấn đề cực kỳ khó chịu với Spring Roo và tôi đã không tìm ra giải pháp chính thức cho.

... Nhưng đây là hai cách giải quyết:

  • Sao chép vào mùa xuân-khía cạnh jar để dự án của bạn sau đó thêm nó vào bạn Projects AspectJ Aspect Đường dẫn
  • Sử dụng Maven để chạy thử nghiệm đơn vị của bạn (và bỏ lỡ thanh màu xanh :()

Đối với tùy chọn một cú nhấp chuột phải vào dự án của bạn chọn Properties-> AspectJ Xây dựng -.> Aspect Đường dẫn Tab

+0

Tôi sẽ chấp nhận câu trả lời này, nhưng tôi không ở vị trí để dễ dàng xác minh nó, vì tôi không còn sử dụng Roo nữa. (Tôi đang ở một công việc khác.) –

+0

@ FarmBoy Bạn không thể nói điều đó bằng cách nói rằng những gì bạn đang sử dụng bây giờ :) –

+0

Groovy/Grails. Tôi thích nó. –

6

ponzao là đúng tôi có thể. có tất cả phép thuật tiêm vào mùa xuân khi lớp thử nghiệm của tôi mở rộng AbstractJunit4SpringContextTests.

ví dụ:

@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" }) 
public class SelfRegistrationTest extends AbstractJUnit4SpringContextTests { 
+0

Dường như có vẻ khó chịu, nhưng có vẻ hiệu quả với tôi. – kipz

1

Lớp thử nghiệm đơn vị của bạn phải có chú thích @MockStaticEntityMethods.

0

Tôi cũng chạy vào cùng một ngoại lệ và mọi thứ đã được định cấu hình chính xác. Tôi đã xóa dự án và nhập lại nó trong STS (SpringSource Tool Suite) và vấn đề này đã biến mất.

Không chắc chắn lý do tại sao điều này được khắc phục nhưng vấn đề này có thể đã được gây ra bởi việc sử dụng Eclipse để quản lý dự án đã tạo Roo trước khi chuyển sang STS trong trường hợp của tôi.

3

Lớp thử nghiệm đơn vị của bạn phải có chú thích @MockStaticEntityMethods.

Chỉ muốn thêm chi tiết vào câu trả lời ở trên bởi @migue vì tôi mất một thời gian để tìm hiểu cách làm cho nó hoạt động. Trang web http://java.dzone.com/articles/mock-static-methods-using-spring-aspects thực sự đã giúp tôi lấy được câu trả lời dưới đây.

Đây là những gì tôi đã làm để tiêm trình quản lý thực thể thông qua lớp thử nghiệm. Đầu tiên chú thích lớp thử nghiệm của bạn với @MockStaticEntityMethods và tạo lớp MockEntityManager (là lớp chỉ thực hiện giao diện EntityManager).

Sau đó, bạn có thể làm như sau trong ServiceExampleTest lớp thử nghiệm của bạn:

@Test 
public void testFoo() { 
    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Foo.entityManager(); 
    MockEntityManager expectedEntityManager = new MockEntityManager() { 
    // TODO override what method you need to return whatever object you test needs 
    }; 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedEntityManager); 

    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
} 

Điều này có nghĩa khi bạn gọi fs.getFoos() các AnnotationDrivenStaticEntityMockingControl sẽ tiêm quản lý thực thể giả của bạn như Foo.entityManager() là một phương pháp tĩnh.

Cũng lưu ý rằng nếu fs.getFoos() gọi các phương thức tĩnh khác trên các lớp thực thể như Foo và Bar, chúng cũng phải được chỉ định như một phần của trường hợp thử nghiệm này. Vì vậy, ví dụ Foo có một phương thức tìm kiếm tĩnh gọi là "getAllBars (Long fooId)" được gọi khi fs.getFoos() được gọi, sau đó bạn sẽ cần thực hiện các thao tác sau để thực hiện công việc AnnotationDrivenStaticEntityMockingControl.

@Test 
public void testFoo() { 
    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Foo.entityManager(); 
    MockEntityManager expectedEntityManager = new MockEntityManager() { 
    // TODO override what method you need to return whatever object you test needs 
    }; 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedEntityManager); 

    // call the static method that gets called by the method being tested in order to 
    // "record" it and then set the expected response when it is replayed during the test 
    Long fooId = 1L; 
    Foo.findAllBars(fooId); 
    List<Bars> expectedBars = new ArrayList<Bar>(); 
    expectedBars.add(new Bar(1)); 
    expectedBars.add(new Bar(2)); 
    AnnotationDrivenStaticEntityMockingControl.expectReturn(expectedBars); 

    FooService fs = new FooServiceImpl(); 
    Set<Foo> foos = fs.getFoos(); 
} 

Hãy nhớ rằng AnnotationDrivenStaticEntityMockingControl phải theo thứ tự fs.getFoos() gọi phương thức tĩnh của nó.

0

thời gian dài sau khi câu hỏi nhưng tôi có một giải pháp làm việc khi cố gắng chạy thử nghiệm đơn vị mùa xuân Roo từ bên trong Eclipse ...

  1. Có dự án mở trong Eclipse
  2. Trong Eclipse, Dự án> sạch > Rebuild (Automatic hoặc Manual không quan trọng)
  3. Khi việc tái xây dựng hoàn tất, trong một cửa sổ giao diện điều khiển, có Maven sạch và tái gói (clean là bắt buộc):

    mvn clean package

hoặc nếu kiểm tra đơn vị của bạn đang thất bại trong maven (và bạn cần Eclipse để gỡ lỗi các bài kiểm tra của bạn)

mvn clean package -Dmaven.test.skip=true 

4. Khi gói là thành công, sau đó làm mới lại trong Eclipse.

Bạn sẽ có thể chạy thử nghiệm đơn vị thành công trở lại trong Eclipse ngay bây giờ. Tôi thấy các mục chỉnh sửa gây ra tần suất lớn nhất của lỗi trình quản lý đối tượng. Khi tôi ở lại rõ ràng về chỉnh sửa chúng, tôi có thể chỉnh sửa các lớp khác và các bài kiểm tra đơn vị sẽ tiếp tục chạy thành công.

0

này làm việc cho tôi với Spring Roo:

import static org.junit.Assert.assertEquals; 

import org.junit.Test; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; 

import com.jitter.finance.analyzer.domain.Address; 

@ContextConfiguration(locations = { "classpath*:/META-INF/spring/applicationContext*.xml"}) 
public class EmTest extends AbstractJUnit4SpringContextTests { 

    @Test 
    public void checkEm(){ 
     Address a = new Address(); 
     a.setName("Primo"); 
     a.persist(); 

     Address b = new Address(); 
     b.setName("Secondo"); 
     b.persist(); 

     for(Address ad : Address.findAllAddresses()){ 
      System.out.println(ad.getName()); 
      assertEquals(ad.getName().charAt(ad.getName().length()-1), 'o'); 
     } 
    } 
} 

Với lớp Địa chỉ như thế này:

import org.springframework.roo.addon.javabean.annotations.RooJavaBean; 
import org.springframework.roo.addon.javabean.annotations.RooToString; 
import org.springframework.roo.addon.jpa.annotations.activerecord.RooJpaActiveRecord; 

@RooJavaBean 
@RooToString 
@RooJpaActiveRecord 
public class Address { 
    private String name; 
} 
Các vấn đề liên quan