2009-12-21 22 views
5

Tôi mới bắt chước và hơi quen thuộc với thử nghiệm đơn vị và cuối cùng đã quyết định cắn đạn vào một dự án mới bắt đầu lên phía trước với một cách tiếp cận TDD nghiêm ngặt. Tuy nhiên tôi có một lớp dịch vụ và phương pháp tôi cần phải truy tìm thêm các xét nghiệm vì nó đã được thúc đẩy từ một mẫu thử nghiệm.Đơn vị kiểm tra dịch vụ có WCF Call (MSUnit + Moq)

Tôi không biết bắt đầu từ mặc dù trên thử nghiệm đặc biệt này ở đâu, đây là lớp học và phương pháp tham gia:

public class PageService : IPageService 
{ 
    private readonly ITestService testServiceClient; 

    public PageService(ITestService testServiceClient) 
    { 
     this.testServiceClient = testServiceClient; 
    } 

    public Page GetPage(Guid websiteId, string pageKey) 
    { 
     Page builtPage = null; 

     // WCF SERVICE CALL I DO NOT WANT EXECUTING WHEN RUNNING UNIT TEST 
     // BUT RATHER WANT A BLANK NEW INSTANCE OF "PAGE" CREATED USING MOQ?? 
     var page = testServiceClient.GetPage(websiteId, pageKey); 

     if (page == null) 
      return null; 

     builtPage = new Page(); 

     [code here to build builtPage if input params ok] ... 

     return builtPage; 
    } 
} 

Những gì tôi đang nỗ lực để làm, là viết một bài kiểm tra, từ này hy vọng tôi có thể mở rộng trên tất cả các hoán vị của các thử nghiệm GetPage(...), nhưng đối với phép thử đầu tiên, hãy thử nghiệm nếu một số websiteIdpageKey hợp lệ đã được chuyển vào, nếu như vậy nhận được một cá thể Page hợp lệ và xác nhận đúng với thử nghiệm đơn vị.

testServiceClient là một khách hàng dịch vụ WCF, điều này được bao bọc trong tuyên bố using() trước đó, nhưng tôi đã chuyển nó ra khỏi đó với hy vọng có được nó với tiêm phụ thuộc như tôi cảm thấy đó sẽ là bước đầu tiên cần thiết để thử nghiệm, từ những gì tôi hiểu, tôi sẽ cần phải cho nó một giả mạo/chế nhạo? wcf khách hàng thay vì nơi testServiceClient.GetPage() trả về bộ dữ liệu đã biết trong bộ nhớ? Hy vọng rằng tôi đang đi đúng hướng ở đó.

Vì vậy, đây là bản thiết kế ban đầu của tôi về kiểm tra đơn vị của tôi (Tôi đang sử dụng khuôn khổ Moq, Setup() là phiên bản mới của Expect() nếu bạn chưa sử dụng ver mới nhất của Moq):

/// <summary> 
/// Tests service returns a valid instance of type `Page` when a valid website and valid page key is tested. 
/// </summary> 
[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.IsInstanceOfType(page, typeof(Page), "Object was not of expected instance type."); 
} 

tôi không có ý tưởng đi đâu từ đây, hoặc nếu tôi đi đúng hướng? Tôi có thể khẳng định không có lỗi cú pháp trên, và tôi nhận được một ngoại lệ:

System.ArgumentException: Invalid setup on a non-overridable member: 
x => x.GetPage(websiteId, "about-us"). 

Tất cả tôi biết là tôi muốn tôi service.GetPage(...) để trả về một thể hiện mới, như websiteIdpageKey là hợp lệ, tuy nhiên tôi không' Tôi muốn nó sử dụng thực tế cuộc gọi WCF testServiceClient.GetPage() ... hy vọng tôi hiểu ý tưởng chế nhạo một cách chính xác. Tôi đã nói với nó một cách chính xác thông qua Moq khi bạn sử dụng testServiceClient.GetPage trên dịch vụ đó, thực sự chỉ cần trả lại một phiên bản mới của trang?

Bất kỳ làm rõ nào được đánh giá cao! Cảm ơn các bạn!

Trả lời

4

Tôi có thể nói rằng bạn đang đi đúng hướng. Nếu ITestService thực sự là một giao diện (như được chỉ ra bởi tên của nó), bạn sẽ có thể Mock nó.

Tuy nhiên, khi bạn xác định Thiết lập, Moq phải có khả năng xác định phương pháp nào bạn muốn, và có vẻ như bạn bằng cách nào đó chỉ ra một phương thức không tồn tại trên giao diện.

Bạn không hiển thị cho chúng tôi giao diện ITestService và chúng tôi cũng không biết loại biến số websiteId.

Nếu bạn xem xét kỹ hơn phương pháp Thiết lập, bạn sẽ thấy rằng đó thực sự là một phương pháp chung, vì vậy có loại hội thảo đang diễn ra khi bạn gọi nó mà không có các tham số chung.

Tôi đoán là tuyên bố của websiteId bằng cách nào đó xung đột với tuyên bố GetPage.Nếu, ví dụ, websiteId được khai báo là object, Moq sẽ chăm sóc một phương pháp có chữ ký này:

Page GetPage(object x, string y); 

đó là không giống như

Page GetPage(Guid x, string y); 

Trong mọi trường hợp, khi bạn quản lý để để thiết lập hoạt động, ý tưởng cơ bản của bạn về bài kiểm tra đơn vị có vẻ ổn. Bạn có thể làm nhiều hơn là chỉ khẳng định rằng các trường hợp không phải là null, vì Mock sẽ đảm bảo rằng các trường hợp trả lại là giống như ví dụ bạn Originall thiết lập:

[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.AreEqual(newPage, page); 
} 

Thông báo các nhiều giá trị hơn Khẳng định.

+0

+1 Câu trả lời hay - @GONeale, chỉ để xác nhận những gì Mark nói, tôi đã chạy một bài kiểm tra nhanh bằng cách sử dụng MOQ và một Giao diện trả về một trang - nó hoạt động tốt. Có vẻ như bạn đang làm một cái gì đó như mockiing một ví dụ cụ thể, nơi GetPage không được khai báo ảo. –

+0

Xin chào các bạn, cảm ơn đã dành thời gian đọc bài đăng của tôi. Well ITestService là một WCF tạo ra dịch vụ khách hàng, (các nhấp chuột phải dự án -> thêm dịch vụ tham khảo) loại. Trong ánh sáng này, tôi không nghĩ rằng tôi có thể tuyên bố nó là 'ảo' vì nó là một lớp được tạo tự động. Tuy nhiên, tôi có thể tạo ra một lớp người gọi WCF đơn giản và thực hiện điều này ảo, điều đó có giúp ích gì cho bạn không? Cảm ơn lời khuyên của Assert. – GONeale

+0

Tôi có hiểu chính xác trong câu nói bằng cách khai báo 'testServiceClient.Setup (x => x.GetPage (..)). Returns (newPage)' cho bất kỳ cuộc gọi nào đến tên của phương thức đó (lồng nhau ngay cả khi phương thức của đối tượng được truyền qua như một tham số chẳng hạn như ví dụ về 'new PageService (testServiceClient.Object)') để thực sự không chạy phương thức * actual * (wcf), nhưng chỉ trả về một cá thể 'newPage' thay thế? Đó có phải là lý do tại sao 'virtual' là bắt buộc, nó ghi đè nó với nội dung phương thức hoàn toàn mới? – GONeale

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