Hi I am having the below interfaces and their implementation. Now, I wanted to unit test the Send()
method which will actually push the message into a queue.
Since I am new to MoQ, not sure how to get it done.
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);
}
}
Here through factory, we decide which type of framework we need to connect and within the factory, we open a connection which passed on to the next class, so that it can be consumed to create and bind queues.
Implementation of IChannel
is the main class which will be used to actually talk with the queue and topics.
The following minimal example shows how to unit test the
ServiceBusChannel.Send
method by providing the necessary dependencies to allow the test to be exercised to completion. It is based on the example provided by the original question.Note: Moq framework was used to mock the abstract dependencies. Their Quickstart provided examples of how to use the framework.
While I believe that the subject under test should not be coupled to concretions, the
AdapternServiceBus
can be used as the entry point for the mocked dependencies as demonstrated above. You can modify to suit you specific needs as I assume the provided code is not the actual code used but an example.You want to test the
Send
method inServiceBusChannel
class.So, in your test, you should instantiate this actual concrete class.
To instantiate a
ServiceBusChannel
, you need anAdapterServiceBus
that allows you to set up yourchannel
variable.Here, the problem is that you depend on a concrete AdapterServiceBus class, so you cannot mock it. You should depend on an interface that exposes the actual behavior you want to mock.
Something like IAdpaterServiceBus that declares
GetChannel();
, (EDIT) or declare theGetChannel()
as a method of your already existingIAdapter
interace).Then you can Mock this :
or
then mock the behavior of GetChannel() :
Then you can pass this to your ServiceBusChannel constructor (modified so it accepts an abstract
IAdapterServiceBus
(orIAdapter
) instead of a concrete instance)