2010-10-11 22 views
6

tôi có mã này trong ứng dụng .NET ứng dụng của tôi sử dụng NServiceBus:Testing Bus.Send trong một ứng dụng sử dụng NServiceBus

Bus.Send<IServiceStarted>(e => 
          { 
            e.ServiceInfo = ReadServiceInfo(); 
            e.EventTime = DateProvider.Now; 
          }); 

Làm thế nào bạn sẽ đi về unit-testing mã như vậy?

+0

Bạn có hỏi về thử nghiệm 'Bus.Send' hoặc mã gửi tin nhắn không? – arootbeer

+0

arootbeer, tôi hỏi về mã thử nghiệm gửi tin nhắn. Mã chính xác mà tôi muốn thử nghiệm được đưa ra trong câu hỏi ở trên. – mgamer

+0

Tôi đã thêm bản chỉnh sửa liên quan đến việc kiểm tra mã đại biểu tại chỗ, trong trường hợp bạn quan tâm. – arootbeer

Trả lời

3

Chừng nào biến Bus của bạn là một ví dụ IBus, bạn chỉ có thể cung cấp một chế giễu IBus thi vào lớp chứa phương pháp này, và xác minh rằng Gửi được gọi vào nó (với các đại biểu thích hợp, nếu bạn muốn) sau khi phương thức được gọi để thử nghiệm. Ngoài ra, bạn sẽ tự mình thử nghiệm bản thân Bus.Send, đó không phải là điều bạn nên làm.

public class ClassThatSendsMessages 
{ 
    private readonly IBus _bus; 
    public ClassThatSendsMessages(IBus bus /*, ... */) 
    { 
     _bus = bus; 
     /* ... */ 
    } 

    public void CodeThatSendsMessage() 
    { 
     /* ... */ 
     _bus.Send<IMyMessage>(mm => mm.Property1 = "123"); 
     /* ... */ 
    } 
} 

public class ClassThatTestsClassThatSendsMessages 
{ 
    public void CallCodeThatSendsMessage() 
    { 
     //Mock IBus object here 
     var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */) 

     objectToTest.CodeThatSendsMessage(); 

     //Verify that IBus mock's Send() method was called 
    } 
} 

Có hai cách để tiếp cận thử nghiệm logic của đại biểu: bạn có thể cố gắng phá vỡ cây biểu hiện được cung cấp hoặc bạn có thể thay đổi thành phương thức đã đặt tên và chuyển nó theo cách đó. Tôi chưa bao giờ nhận được sâu vào biểu thức, vì vậy tôi sẽ cung cấp một ví dụ về sau:

public static class MyMessageBuilder 
{ 
    public static void Build(IMyMessage message) { /* ... */ } 
} 

public class ClassThatTestsMyMessageBuilder 
{ 
    public void CallCodeThatBuildsMessage() 
    { 
     var message = Test.CreateInstance<IMyMessage>(MyMessageBuilder.Build); 

     //Verify message contents 
    } 
} 

Cách sử dụng:

public class ClassThatSendsMessages 
{ 
    private readonly IBus _bus; 
    public static Action<IMyMessage> BuildMessage { private get; set; } 
    public ClassThatSendsMessages(IBus bus /*, ... */) 
    { 
     _bus = bus; 
     /* ... */ 
    } 

    public void CodeThatSendsMessage() 
    { 
     /* ... */ 
     _bus.Send<IMyMessage>(mm => BuildMessage (mm)); 
     /* ... */ 
    } 
} 

Tôi không biết của một container có thể làm tiêm đại biểu đến nhà xây dựng, nhưng sau đó tôi đã không nhìn rất khó, hoặc, vì vậy mà có thể là một cách tốt hơn để thiết lập các đại biểu.

EDIT

Như tôi vừa mới chạy vào vấn đề này trong các thử nghiệm của riêng tôi, và tôi không thực sự giống như có để kéo phương pháp ra vào xây dựng riêng của mình. Vì vậy, tôi đặt ra để khám phá nếu tôi có thể kiểm tra các đại biểu "tại chỗ". Nó chỉ ra rằng bạn có thể:

public class ClassThatTestsClassThatSendsMessages 
{ 
    public void CallCodeThatSendsMessage() 
    { 
    Action<IMyMessage> messageAction = null; 

    //Mock IBus object here 
    mockedIBus.Setup(b => b.Send(Args.IsAny<Action<IMyMessage>>())) 
     .Callback((Action<IMyMessage> a) => messageAction = a); 
    var myMessage = Test.CreateInstance<IMyMessage>(); 

    var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */) 

    //Run the code that sends the message 
    objectToTest.CodeThatSendsMessage(); 
    //Run the code that populates the message 
    messageAction(myMessage); 

    //Verify expectations on Setups 
    //Verify the message contents; 
    } 
} 

Có cân bằng ở đây - kéo builder nhắn ra một giao diện được chắc chắn phù hợp hơn với SRP hơn để lại nó như là một đại biểu inline (như kiểm tra chứng minh rõ ràng: bạn phải Hành động hai lần để kiểm tra tất cả mã). Tuy nhiên, nó trình bày lợi ích ở cả kích thước mã và khả năng đọc.

Ngoài ra, này là Moq cụ thể; Tôi không biết liệu có thể đưa đại biểu trở lại từ mô hình RhinoMocks hay không, hay cú pháp sẽ là gì.

+1

Nếu mã đang được thử nghiệm là một trình xử lý tin nhắn, thì bạn có thể sử dụng thư viện NServiceBus.Testing có thể mô phỏng bus cho bạn, và nếu bạn sử dụng setter injection cho thuộc tính IBus, nó sẽ đưa nó vào trình xử lý của bạn. –

+0

arootbeer, phần khó khăn đối với tôi là làm cách nào để xác minh rằng phương thức Gửi đã được gọi với đại biểu thích hợp? Rhino Mocks cung cấp một phương thức AssertWasCalled chấp nhận ràng buộc trên các đối số, nhưng nó có một hạn chế cho phép bạn xác minh xem phương thức đã được gọi với một đại biểu thích hợp chưa? – mgamer

+0

Bạn có thể thử sử dụng GetArgumentsForCallsMadeOn để kéo đại biểu và kiểm tra các thuộc tính của nó: http://kashfarooq.wordpress.com/2009/01/10/rhino-mocks-and-getargumentsforcallsmadeon/ – PatrickSteele

2

Kiểm tra khung kiểm tra đi kèm với NSB, sử dụng tê giác bên dưới: http://nservicebus.com/UnitTesting.aspx. có một số mẫu trong phần tải xuống sử dụng nó với NUnit. Bạn có thể làm cho nó hoạt động dưới MSTest.

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