2011-09-02 34 views
5

Đây là câu hỏi đầu tiên của tôi vì vậy hãy tử tế! :)Làm thế nào để sử dụng Moq để kiểm tra một phương pháp không có giá trị trả về?

Điều tôi đang cố gắng thực hiện là viết một số thử nghiệm cho một lớp người quản lý trong khi xây dựng thêm nhiều phiên bản mới của một hạng mục đơn lẻ vào danh sách. Khi UpdateAllItems được gọi trong lớp người quản lý này, ý định là lặp lại danh sách và gọi gia tăng trên mỗi mục đơn lẻ.

Lớp người quản lý là mã của tôi, nhưng lớp hạng mục duy nhất không phải là vì vậy tôi không thể sửa đổi nó.

Tôi sử dụng NUnit cho khung kiểm tra và bắt đầu làm việc với Moq. Bởi vì lớp người quản lý sử dụng hạng mục đơn lẻ nên tôi nghĩ rằng tôi cần phải sử dụng một Moq vì vậy tôi chỉ đang thử nghiệm người quản lý chứ không phải là một mục duy nhất.

Làm cách nào để viết các bài kiểm tra cho phương pháp UpdateAllItems của tôi? (Về mặt kỹ thuật tôi nên viết các bài kiểm tra đầu tiên mà tôi biết).

Dưới đây là một mã số mẫu mà đưa ra một ý tưởng chung của những gì tôi đang làm việc với ...

public class SingleItem_CodeCantBeModified 
{ 
    public int CurrentValue { get; private set; } 

    public SingleItem_CodeCantBeModified(int startValue) 
    { 
     CurrentValue = startValue; 
    } 

    public void Increment() 
    { 
     CurrentValue++; 
    } 
} 

public class SingleItemManager 
{ 
    List<SingleItem_CodeCantBeModified> items = new List<SingleItem_CodeCantBeModified>(); 

    public SingleItemManager() 
    { 
     items.Add(new SingleItem_CodeCantBeModified(100)); 
     items.Add(new SingleItem_CodeCantBeModified(200)); 
    } 

    public void UpdateAllItems() 
    { 
     items.ForEach(item => item.Increment()); 
    } 
} 

Cảm ơn trước cho tất cả sự giúp đỡ!

+0

Lớp học này hữu ích như thế nào? Nó tạo ra một danh sách riêng của các quầy và cập nhật mỗi mục mỗi khi một phương thức được gọi. Phải có một số thay đổi trong hành vi của đối tượng .. ví dụ: nếu UpdateAllItems không hoạt động - điều gì sẽ thay đổi được quan sát? – Gishu

Trả lời

5

Câu trả lời đơn giản là bạn không thể. Phương thức mà các cuộc gọi UpdateAllItems (Increment()) không phải là ảo, do đó bạn sẽ không thể giả mạo nó.

lựa chọn của bạn, như tôi nhìn thấy nó, bao gồm:

  • Đừng thử nghiệm UpdateAllItems ở tất cả. Việc thực hiện của nó là tầm thường, vì vậy đây là một tùy chọn để xem xét (mặc dù không lý tưởng).
  • Tạo các trường hợp thực tế SingleItem_CodeCantBeModified trong thử nghiệm của bạn. Người theo chủ nghĩa thuần túy sẽ nói rằng bạn không còn có thử nghiệm đơn vị vào thời điểm này nữa, nhưng nó vẫn có thể là một thử nghiệm hữu ích.
  • Thêm giao diện ISingleItem và lớp SingleItemAdapter : ISingleItem chứa tham chiếu đến SingleItem_CodeCantBeModified và chuyển tiếp cuộc gọi. Sau đó, bạn có thể viết SingleItemManager để hoạt động trên ISingleItem s và bạn sẽ được tự do chuyển qua thử nghiệm ISingleItem trong thử nghiệm của mình. (Tùy thuộc vào cách hệ thống của bạn được thiết lập, bạn thậm chí có thể có thể đi xuống từ SingleItem_CodeCantBeModified, thực hiện giao diện trên hậu duệ của bạn, và sử dụng các đối tượng thay vì viết một adapter.)

Đó Tùy chọn cuối cùng mang đến cho bạn hầu hết các tùy chọn, nhưng với chi phí của một số phức tạp. Chọn tùy chọn phù hợp nhất với những gì bạn đang cố gắng hoàn thành.

1

Người quản lý của bạn quá phụ thuộc vào Mục (trong List<Item>). Bạn có thể trích xuất danh sách dân số thành lớp riêng biệt để có thể thử không? ví dụ:

public SingleItemManager() 
{ 
    items.Add(ItemRepository.Get(100)); 
    items.Add(ItemRepository.Get(200)); 
} 

Testing (một số mã bỏ qua):

int i = 0; 

var itemMock = new Mock<Item>(); 
itemMock.Setup(i => i.Increment()).Callback(() => i++); 

var repositoryMock = new Moc<ItemRepository>(); 
repositoryMock.Setup(r => r.Get(It.IsAny<int>()).Returns(itemMock.Object); 

var manager = new SingleItemManager(); 
manager.UpdateAllItems(); 

Assert.AreEqual(i, 1); 
-1

Thay vì cứng mã hóa các mặt hàng cụ thể bổ sung của bạn, có SingleItem_CodeCantBeModified thực hiện một giao diện (hoặc nhúng nó trong một wrapper mà thực hiện giao diện) sau đó vượt qua trong một nhà máy (mới) sẽ tạo ra các mặt hàng này.

Trong thử nghiệm của bạn, bạn sẽ tạo ra một mô hình của nhà máy để chuyển sang lớp Manager, sau đó bạn có thể theo dõi những phương thức được gọi trên đối tượng giả đó.

Mặc dù điều này sẽ là nhiều hơn về kiểm tra nội bộ của hệ thống, chứ không phải các sản phẩm phụ. Giao diện nào được quản lý thực hiện? Nếu nó không tự chứng minh bên ngoài, bạn đang thử nghiệm kết quả nào?

+0

SingleItem_ ** CodeCantBeModified ** – riezebosch

+0

@riezebosch: Nếu đẩy đến xô bạn có thể tạo một đối tượng proxy thực hiện một giao tiếp và chỉ cần đi qua các cuộc gọi phương thức. Nó không hoàn toàn giống như gettting lớp để thực hiện giao diện nhưng có tác dụng tương tự. – Chris

0

Như thường lệ, bạn có thể thêm cấp độ gián tiếp khác.

  1. Tạo một lớp bao bọc xung quanh SingleItem_CodeCantBeModified
  2. Hãy wrapper này kế thừa giao diện IItem
  3. Hãy SingleItemManager phụ thuộc vào IItem thay vì SingleItem_CodeCantBeModified

HOẶC

Nếu Increment là một phương pháp ảo (Tôi hiểu nó không có trong mã mẫu của bạn, nhưng chỉ trong trường hợp), sử dụng partial mocking.

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