Đây là cách tiếp cận của tôi. Nó có chi phí về thời gian vì đây là một bài kiểm tra tái cấu trúc theo 4 giai đoạn.
Những gì tôi sẽ phơi bày có thể phù hợp với các thành phần có độ phức tạp cao hơn so với những gì được nêu trong ví dụ của câu hỏi.
Dù sao, chiến lược là hợp lệ cho bất kỳ ứng cử viên thành phần nào được chuẩn hóa bởi một giao diện (DAO, Dịch vụ, Bộ điều khiển, ...).
1. Giao diện
Cho phép tập hợp tất cả các phương thức công khai từ MyDocumentService và cho phép đặt tất cả chúng vào cùng một giao diện. Ví dụ. Nếu nó đã tồn tại, hãy sử dụng cái đó thay vì đặt bất kỳ cái mới nào .
public interface DocumentService {
List<Document> getAllDocuments();
//more methods here...
}
Sau đó, chúng tôi buộc MyDocumentService triển khai giao diện mới này.
Càng xa càng tốt. Không có thay đổi lớn nào được thực hiện, chúng tôi tôn trọng hợp đồng hiện tại và các hành vi vẫn chưa được xử lý.
public class MyDocumentService implements DocumentService {
@Override
public List<Document> getAllDocuments(){
//legacy code here as it is.
// with no changes ...
}
}
2. Kiểm tra đơn vị mã kế thừa
Ở đây chúng tôi có công việc khó khăn. Để thiết lập một bộ thử nghiệm. Chúng ta nên đặt càng nhiều trường hợp càng tốt: trường hợp thành công và cả trường hợp lỗi. Những cái cuối cùng là vì chất lượng của kết quả.
Bây giờ, thay vì kiểm tra MyDocumentService, chúng tôi sẽ sử dụng giao diện làm hợp đồng sẽ được kiểm tra.
Tôi sẽ không đi vào chi tiết, vì vậy hãy tha thứ cho tôi Nếu mã của tôi trông quá đơn giản hoặc quá bất khả tri
public class DocumentServiceTestSuite {
@Mock
MyDependencyA mockDepA;
@Mock
MyDependencyB mockDepB;
//... More mocks
DocumentService service;
@Before
public void initService(){
service = MyDocumentService(mockDepA, mockDepB);
//this is purposed way to inject
//dependencies. Replace it with one you like more.
}
@Test
public void getAllDocumentsOK(){
// here I mock depA and depB
// wanted behaivors...
List<Document> result = service.getAllDocuments();
Assert.assertX(result);
Assert.assertY(result);
//... As many you think appropiate
}
}
Giai đoạn này mất nhiều thời gian hơn bất kỳ cách nào khác trong phương pháp này. Và đó là điều quan trọng nhất vì nó sẽ đặt điểm tham chiếu cho các so sánh trong tương lai.
Lưu ý: Do không có thay đổi lớn nào được thực hiện và hành vi vẫn chưa được xử lý. Tôi đề nghị làm một thẻ ở đây vào SCM. Thẻ hoặc chi nhánh không quan trọng. Chỉ cần làm một phiên bản.
Chúng tôi muốn nó cho các bản rollback, so sánh các phiên bản và có thể là để thực thi song song mã cũ và mã mới.
3. Tái cấu trúc
Refactor sẽ được thực hiện thành một thành phần mới. Chúng tôi sẽ không làm bất kỳ thay đổi trên mã hiện có. Bước đầu tiên là dễ dàng như sao chép và dán MyDocumentService và đổi tên thành CustomDocumentService (ví dụ).
Lớp mới tiếp tục triển khai DocumentService . Sau đó đi và tái cấu trúc getAllDocument () . (Hãy bắt đầu bằng một. Bộ tái cấu trúc pin)
Nó có thể yêu cầu một số thay đổi trên giao diện / phương thức của DAO. Nếu vậy, đừng thay đổi mã hiện có. Thực hiện phương pháp của riêng bạn trong giao diện DAO. Chú thích mã cũ là Không dùng nữa và bạn sẽ biết sau này về những gì cần xóa.
Điều quan trọng là không phá vỡ / thay đổi triển khai hiện có. Chúng tôi muốn thực hiện song song cả hai dịch vụ và sau đó so sánh kết quả.
public class CustomDocumentService implements DocumentService {
@Override
public List<Document> getAllDocuments(){
//new code here ...
//due to im refactoring service
//I do the less changes possible on its dependencies (DAO).
//these changes will come later
//and they will have their own tests
}
}
4. Cập nhật DocumentServiceTestSuite
Ok, bây giờ là phần dễ dàng hơn. Để thêm các thử nghiệm của thành phần mới.
public class DocumentServiceTestSuite {
@Mock
MyDependencyA mockDepA;
@Mock
MyDependencyB mockDepB;
DocumentService service;
DocumentService customService;
@Before
public void initService(){
service = MyDocumentService(mockDepA, mockDepB);
customService = CustomDocumentService(mockDepA, mockDepB);
// this is purposed way to inject
//dependencies. Replace it with the one you like more
}
@Test
public void getAllDocumentsOK(){
// here I mock depA and depB
// wanted behaivors...
List<Document> oldResult = service.getAllDocuments();
Assert.assertX(oldResult);
Assert.assertY(oldResult);
//... As many you think appropiate
List<Document> newResult = customService.getAllDocuments();
Assert.assertX(newResult);
Assert.assertY(newResult);
//... The very same made to oldResult
//this is optional
Assert.assertEquals(oldResult,newResult);
}
}
Bây giờ chúng ta có oldResult và newResult đều được xác nhận độc lập nhưng chúng ta cũng có thể so sánh với nhau. Xác nhận cuối cùng này là tùy chọn và nó phụ thuộc vào kết quả. Có thể không thể so sánh được.
Có thể không tạo ra quá nhiều sự phức tạp để so sánh hai bộ sưu tập theo cách này, nhưng sẽ hợp lệ cho bất kỳ loại đối tượng nào khác (pojos, thực thể mô hình dữ liệu, DTOs, Wrappers, kiểu bản địa ...)
Ghi chú
Tôi sẽ không dám nói làm thế nào để kiểm tra đơn vị hoặc làm thế nào để sử dụng libs giả. Tôi không dám nói bạn phải làm thế nào để tái cấu trúc. Những gì tôi muốn làm là đề xuất một chiến lược toàn cầu. Làm thế nào để đưa nó về phía trước phụ thuộc vào bạn. Bạn biết chính xác mã là như thế nào, độ phức tạp của nó và nếu chiến lược như vậy đáng để thử. Sự kiện như thời gian và tài nguyên quan trọng ở đây. Cũng quan trọng những gì bạn mong đợi từ các thử nghiệm này trong tương lai.
Tôi đã bắt đầu các ví dụ của mình bằng một Dịch vụ và tôi sẽ làm theo DAO, v.v. Đi sâu vào mức độ phụ thuộc. Ít nhiều nó có thể được mô tả như là chiến lược từ dưới lên . Tuy nhiên, đối với các thay đổi / bộ tái cấu trúc nhỏ ( như ví dụ được hiển thị trong ví dụ về chuyến tham quan ), từ dưới lên sẽ thực hiện công việc dễ dàng hơn. Bởi vì phạm vi của những thay đổi là ít.
Cuối cùng, tùy thuộc vào bạn để loại bỏ mã không dùng nữa và để chuyển hướng phụ thuộc cũ sang mã mới.
Loại bỏ các bài kiểm tra cũng không dùng nữa và công việc được thực hiện. Nếu bạn đã phiên bản giải pháp cũ với các thử nghiệm của nó, bạn có thể kiểm tra và so sánh lẫn nhau bất cứ lúc nào.
Do hậu quả của rất nhiều công việc, bạn có mã kế thừa được kiểm tra, xác nhận và phiên bản. Và mã mới, đã được thử nghiệm, xác nhận và sẵn sàng để được phiên bản.