2009-04-07 38 views
18

Tôi vừa chuyển sang Moq và đã gặp sự cố. Tôi đang thử nghiệm một phương thức tạo ra một cá thể mới của một đối tượng nghiệp vụ, thiết lập các thuộc tính của đối tượng từ các giá trị đầu vào của người dùng và gọi một phương thức (SaveCustomerContact) để lưu đối tượng mới. Đối tượng nghiệp vụ được truyền dưới dạng đối số ref vì nó đi qua lớp truy cập từ xa. Tôi cần phải kiểm tra rằng đối tượng được chuyển đến SaveCustomerContact có tất cả các thuộc tính của nó được thiết lập như mong đợi, nhưng vì nó được khởi tạo như mới trong phương thức điều khiển, tôi không thể làm như vậy.Xác minh giá trị tham số tham chiếu với Moq

public void AddContact() { 

    var contact = new CustomerContact() { CustomerId = m_model.CustomerId }; 

    contact.Name = m_model.CustomerContactName; 
    contact.PhoneNumber = m_model.PhoneNumber; 
    contact.FaxNumber = m_model.FaxNumber; 
    contact.Email = m_model.Email; 
    contact.ReceiveInvoiceFlag = m_model.ReceiveInvoiceFlag; 
    contact.ReceiveStatementFlag = m_model.ReceiveStatementFlag; 
    contact.ReceiveContractFlag = m_model.ReceiveContractFlag; 
    contact.EmailFlag = m_model.EmailFlag; 
    contact.FaxFlag = m_model.FaxFlag; 
    contact.PostalMailFlag = m_model.PostalMailFlag; 
    contact.CustomerLocationId = m_model.CustomerLocationId; 

    RemotingHandler.SaveCustomerContact(ref contact); 
} 

Dưới đây là các bài kiểm tra:

[TestMethod()] 
public void AddContactTest() { 

    int customerId = 0; 

    string name = "a"; 

    var actual = new CustomerContact(); 

    var expected = new CustomerContact() { 
     CustomerId = customerId, 
     Name = name 
    }; 

    model.Setup(m => m.CustomerId).Returns(customerId); 
    model.SetupProperty(m => model.CustomerContactName, name); 
    model.SetupProperty(m => m.PhoneNumber, string.Empty); 
    model.SetupProperty(m => m.FaxNumber, string.Empty); 
    model.SetupProperty(m => m.Email, string.Empty); 
    model.SetupProperty(m => m.ReceiveInvoiceFlag, false); 
    model.SetupProperty(m => m.ReceiveStatementFlag, false); 
    model.SetupProperty(m => m.ReceiveContractFlag, false); 
    model.SetupProperty(m => m.EmailFlag, false); 
    model.SetupProperty(m => m.FaxFlag, false); 
    model.SetupProperty(m => m.PostalMailFlag, false); 
    model.SetupProperty(m => m.CustomerLocationId, 0); 

    remote 
     .Setup(r => r.SaveCustomerContact(ref actual)) 
     .Callback(() => Assert.AreEqual(actual, expected)); 

    target.AddContact(); 

} 

Đây mới chỉ là gần đây nhất của nhiều nỗ lực để có được Ahold của tham số đó. Để tham khảo, giá trị của thực tế không thay đổi từ trạng thái ban đầu (được xây dựng) của nó.

Di chuyển Assert.AreEqual (dự kiến, thực tế) sau khi cuộc gọi đích không thành công. Nếu tôi thêm .Verifiable() vào thiết lập thay vì .CallBack và sau đó gọi remote.Verify sau khi mục tiêu (hoặc, tôi giả định, thiết lập mô hình để nghiêm ngặt) nó luôn luôn thất bại vì tham số tôi cung cấp trong thử nghiệm không phải là ví dụ tương tự như trường hợp được tạo trong phương thức bộ điều khiển.

Tôi đang sử dụng Moq 3.0.308.2. Bất kỳ ý tưởng về cách kiểm tra này sẽ được đánh giá cao. Cảm ơn!

Trả lời

19

Tôi không thể cung cấp cho bạn một giải pháp chính xác, nhưng một giải pháp thay thế là ẩn các ngữ nghĩa truyền qua sau một bộ điều hợp, lấy tham số theo giá trị và chuyển nó tới RemotingHandler.Điều này sẽ được dễ dàng hơn để chế nhạo, và sẽ loại bỏ các "ref" mụn cóc từ giao diện (Tôi luôn nghi ngờ các thông số ref :-))

EDIT:

Hoặc bạn có thể sử dụng một cuống thay vì một mock Ví dụ:

public class StubRemotingHandler : IRemotingHandler 
{ 
    public CustomerContact savedContact; 

    public void SaveCustomerContact(ref CustomerContact contact) 
    { 
     savedContact = contact; 
    } 
} 

bạn bây giờ có thể kiểm tra các đối tượng được lưu trong thử nghiệm của bạn:

IRemotingHandler remote = new StubRemotingHandler(); 
... 
//pass the stub to your object-under-test 
... 
target.AddContact(); 
Assert.AreEqual(expected, remote.savedContact); 

bạn cũng có nói trong bình luận của bạn:

tôi ghét để bắt đầu một tiền lệ của gói bit ngẫu nhiên của các phụ trợ để tôi có thể viết bài kiểm tra dễ dàng hơn

Tôi nghĩ đó là chính xác tiền lệ bạn cần phải thiết lập! Nếu mã của bạn không thể kiểm tra được, bạn sẽ tiếp tục đấu tranh để kiểm tra nó. Giúp kiểm tra và tăng mức độ phù hợp của bạn dễ dàng hơn.

+0

Tôi đoán tôi không chắc chắn làm thế nào bạn sẽ stub này hoặc là (mặc dù tôi không biết nhiều về khai). Bạn có thể giải thích về cách mà có thể được xử lý? –

+0

Ngoài ra, nhiều như tôi đồng ý với bạn về vấn đề ref, đó là cách lớp remoting của chúng tôi hoạt động và tôi ghét bắt đầu một tiền lệ của gói bit ngẫu nhiên của backend để tôi có thể viết các bài kiểm tra dễ dàng hơn. –

+0

Tôi đã có một vấn đề tương tự, và có được như vậy zeroed trong ngày làm MoQ làm việc, tôi quên tôi có thể viết bài của riêng tôi! Cảm ơn bạn. –

9

Thật không may, tôi không chắc chắn rằng điều này là có thể nếu không có sự hỗ trợ trực tiếp từ Moq. Vấn đề là các biểu thức Lambda không hỗ trợ ref hoặc out.

"Một biểu thức lambda không thể trực tiếp nắm bắt một ref hoặc ra tham số từ một phương pháp kèm theo."

http://msdn.microsoft.com/en-us/library/bb397687.aspx

Tôi thậm chí không thể có được một ví dụ như của bạn để làm việc. Thêm ref vào thiết lập không biên dịch được.

Bạn có thể muốn kiểm tra các cuộc thảo luận để biết thêm Moq http://groups.google.com/group/moqdisc

Chúc may mắn.

+0

Câu trả lời hay! :) – Delashmate

10

Phiên bản mới nhất của Moq hỗ trợ kịch bản này.

Taken từ QuickStart tại http://code.google.com/p/moq/wiki/QuickStart:

// ref arguments 
var instance = new Bar(); 
// Only matches if the ref argument to the invocation is the same instance 
mock.Setup(foo => foo.Submit(ref instance)).Returns(true); 
+6

Cảm ơn bạn đã phản hồi. Tôi đã thấy điều này nhanh chóng (trên thực tế, tôi đã thuyết phục ông chủ của tôi nâng cấp lên phiên bản mới nhất của Moq bởi vì tôi đã làm việc trên nó). Thật không may, các hành vi dường như không làm theo những gì là (rất không rõ ràng) được đề xuất bởi "Chỉ phù hợp nếu đối số ref để gọi là trường hợp tương tự". –

0

Tôi đã gặp phải vấn đề tương tự. Bit Tôi nhận giải pháp bằng cách sử dụng Moq mới nhất và chuyển giá trị như

var instance = new Bar(); Mock.Setup (foo => foo.Submit (ref instance)). Returns (true);

Trước đó, tôi đã sử dụng cùng một phương pháp, nhưng tôi đã không nhận được trả lại là đúng sự thật.

Bên trong trường hợp hàm thực tế đã được tạo và ghi đè trường hợp được truyền từ lớp kiểm tra đơn vị đã gây ra sự cố. Tôi đã loại bỏ cá thể tạo bên trong lớp thực tế và sau đó nó hoạt động.

Hy vọng nó sẽ giúp bạn.

cảm ơn

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