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, mã 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ì.
Bạn có hỏi về thử nghiệm 'Bus.Send' hoặc mã gửi tin nhắn không? – arootbeer
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
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