您好我有以下接口及其实现。现在,我想对Send()
方法进行单元测试,该方法实际上会将消息推送到队列中。
由于我是MoQ的新手,不知道如何完成它。
public interface IAdapter
{
IChannel UseQueue(QueueDetail queueDetail);
}
public interface IChannel
{
void Send(string key, byte[] message);
}
public class AdapternServiceBus : IAdapter
{
readonly IConnection connection;
readonly IModel channel;
public AdapternServiceBus(IConnection connection, IModel channel)
{
this.connection = connection;
this.channel = channel;
}
public IChannel BindAndUseQueue(QueueDetail queueDetail)
{
// Logic of creating and binding queue
return new ServiceBusChannel(this, queueDetail.QueueName);
}
public IModel GetChannel()
{
return channel;
}
}
public class ServiceBusChannel : IChannel
{
readonly string containerName;
IModel channel;
public ServiceBusChannel(AdapternServiceBus adapter, string containerName)
{
this.containerName = containerName;
channel = adapter.GetChannel();
}
public void Send(string key, byte[] message)
{
// Publish the message
channel.BasicPublish(exchangeName, key, null, message);
}
}
通过工厂,我们决定我们需要连接哪种类型的框架,并且在工厂内,我们打开一个传递给下一个类的连接,以便可以使用它来创建和绑定队列。
IChannel
的实现是用于实际与队列和主题交谈的主要类。
答案 0 :(得分:3)
您想在Send
课程中测试ServiceBusChannel
方法。
因此,在您的测试中,您应该实例化这个实际的具体类。
要实例化ServiceBusChannel
,您需要AdapterServiceBus
,以便设置channel
变量。
这里,问题是您依赖于具体的AdapterServiceBus类,因此您无法模拟它。您应该依赖于公开您要模拟的实际行为的接口。
IAdpaterServiceBus之类的东西,声明GetChannel();
,(编辑) 或声明GetChannel()
作为已存在的IAdapter
interace的方法< / em>的
然后你可以嘲笑这个:
var mockedAdapter = new Mock<IAdapterServiceBus>();
或
var mockedAdapter = new Mock<IAdapter>(); // if you added GetChannel() to IAdapter
然后模拟GetChannel()的行为:
mockedAdapter.Setup(x => x.GetChannel())
.Returns( /* some mocked string value for your channel */);
然后您可以将其传递给ServiceBusChannel构造函数(已修改,因此它接受抽象IAdapterServiceBus
(或 IAdapter
)而不是具体实例)
var service = new ServiceBusChannel(mockedAdapter.Object, containerName);
答案 1 :(得分:2)
以下最小示例显示了如何通过提供必要的依赖关系来对ServiceBusChannel.Send
方法进行单元测试,以允许执行测试。它基于原始问题提供的示例。
[TestClass]
public class ServiceBusChannel_Should {
[TestMethod]
public void SendMessage() {
//Arrange
var channel = Mock.Of<IModel>();
var connection = Mock.Of<IConnection>();
var adapter = new AdapternServiceBus(connection, channel);
var key = "somekey";
var message = Encoding.UTF8.GetBytes("Hello World");
var subject = new ServiceBusChannel(adapter, "containerName");
//Act
subject.Send(key, message);
//Assert
Mock.Get(channel).Verify(_ => _.BasicPublish(It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<bool>(),
It.IsAny<IBasicProperties>(),
It.IsAny<byte[]>())
, Times.AtLeastOnce());
}
}
注意:Moq框架用于模拟抽象依赖项。他们的Quickstart提供了如何使用框架的示例。
虽然我认为测试中的主题不应该与具体结果相结合,但AdapternServiceBus
可以用作模拟依赖项的入口点,如上所示。您可以修改以满足您的特定需求,因为我假设提供的代码不是使用的实际代码,而是一个示例。