2012-02-09 19 views
10

Tôi đang phát triển một ứng dụng Java với nhiều truy vấn tiêu chuẩn Hibernate phức tạp. Tôi muốn kiểm tra các tiêu chí này để đảm bảo rằng họ đang chọn đúng, và chỉ có quyền, đối tượng. Tất nhiên, cách tiếp cận này là thiết lập cơ sở dữ liệu trong bộ nhớ (ví dụ: HSQL) và trong mỗi lần kiểm tra, thực hiện một chuyến đi khứ hồi tới cơ sở dữ liệu đó bằng các tiêu chí và sau đó xác nhận rằng kết quả truy vấn phù hợp với mong đợi của tôi.Làm thế nào để kiểm tra các truy vấn tiêu chuẩn Hibernate mà không cần sử dụng bất kỳ cơ sở dữ liệu nào?

Nhưng tôi đang tìm một giải pháp đơn giản hơn, vì các tiêu chí Hibernate chỉ là một kiểu vị ngữ logic đặc biệt về các đối tượng Java. Vì vậy, theo lý thuyết, chúng có thể được kiểm tra mà không cần truy cập vào bất kỳ cơ sở dữ liệu nào cả. Ví dụ, giả sử rằng có một thực thể gọi là Cat:

class Cat { 
    Cat(String name, Integer age){ 
     this.name = name; 
     this.age = age; 
    } 
    ... 
} 

Tôi muốn làm điều gì đó như thế này, để tạo ra các tiêu chí truy vấn:

InMemoryCriteria criteria = InMemoryCriteria.forClass(Cat.class) 
    .add(Restrictions.like("name", "Fritz%")) 
    .add(Restrictions.or(
     Restrictions.eq("age", new Integer(0)), 
     Restrictions.isNull("age"))) 

assertTrue(criteria.apply(new Cat("Foo", 0))) 
assertTrue(criteria.apply(new Cat("Fritz Lang", 12))) 
assertFalse(criteria.apply(new Cat("Foo", 12))) 

Các tiêu chí có thể được sử dụng trong mã sản xuất như thế này :

criteria.getExecutableCriteria(session); //similar to DetachedCriteria 

Có thư viện Java nào làm cho loại thử nghiệm này khả thi không?

Trả lời

15

Bạn có thể sử dụng một khung mocking như Mockito để giả lập tất cả các lớp Hibernate có liên quan và xác định hành vi mong đợi của các mocks này.

Âm thanh giống như nhiều mã, nhưng vì API tiêu chí Hibernate là giao diện thông thạo, tất cả các phương thức Criteria trả về phiên bản mới Criteria. Vì vậy, xác định hành vi mô phỏng mà là phổ biến cho tất cả các bài kiểm tra là đơn giản. Dưới đây là một ví dụ sử dụng Mockito

@Mock 
private SessionFactory sessionFactory; 

@Mock 
Session session; 

@Mock 
Criteria criteria; 

CatDao serviceUnderTest; 

@Before 
public void before() 
{ 
    reset(sessionFactory, session, criteria); 
    when(sessionFactory.getCurrentSession()).thenReturn(session); 
    when(session.createCriteria(Cat.class)).thenReturn(criteria); 
    when(criteria.setFetchMode(anyString(), (FetchMode) anyObject())).thenReturn(criteria); 
    when(criteria.setFirstResult(anyInt())).thenReturn(criteria); 
    when(criteria.setMaxResults(anyInt())).thenReturn(criteria); 
    when(criteria.createAlias(anyString(), anyString())).thenReturn(criteria); 
    when(criteria.add((Criterion) anyObject())).thenReturn(criteria); 

    serviceUnderTest = new CatDao(sessionFactory); 
} 

Tất cả các phương pháp của Criteria trở lại mô hình các mô hình một lần nữa.

Trong thử nghiệm cụ thể, bạn sẽ sử dụng câu lệnh ArgumentCaptorverify để điều tra những gì đã xảy ra với số Criteria được chế nhạo.

@Test 
public void testGetCatByName() 
{ 
    ArgumentCaptor<Criterion> captor = ArgumentCaptor.forClass(Criterion.class); 

    serviceUnderTest.getCatByName("Tom"); 

    // ensure a call to criteria.add and record the argument the method call had 
    verify(criteria).add(captor.capture()); 

    Criterion criterion = captor.getValue(); 

    Criterion expectation = Restrictions.eq("name", "Tom"); 

    // toString() because two instances seem never two be equal 
    assertEquals(expectation.toString(), criterion.toString()); 
} 

Vấn đề tôi thấy với loại đơn vị này là họ đặt ra rất nhiều kỳ vọng về lớp đang được kiểm tra. Nếu bạn nghĩ về serviceUnderTest làm hộp đen, bạn không thể biết cách truy xuất đối tượng mèo theo tên. Nó cũng có thể sử dụng tiêu chí LIKE hoặc thậm chí 'IN' thay vì =, hơn nữa nó có thể sử dụng tiêu chí Example. Hoặc nó có thể thực thi truy vấn SQL nguyên gốc.

+4

Cảm ơn bạn đã trả lời! Tuy nhiên, như bạn chỉ ra, loại kiểm tra này xác minh cách lớp * được triển khai *, không phải cách nó được cho là * cư xử *. Ngoài ra, thử nghiệm này tập trung vào một dịch vụ khác, điều đó xảy ra để sử dụng các tiêu chí. Mặc dù điều này chắc chắn là một phần quan trọng của chức năng, nó nên được tương đối dễ dàng để kiểm tra (bằng cách tách lớp với việc sử dụng quyền của giao diện, tách trách nhiệm, vv). Ở đây, tôi quan tâm nhiều hơn đến việc kiểm tra chính đối tượng Tiêu chí. –

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