0

I have the below method:

public void Enqueue(ICommand itemToQueue)
{
    if (itemToQueue == null)
    {
        throw new ArgumentNullException("itemToQueue");
    }

    // Using the dynamic keywork to ensure the type passed in to the generic
    // method is the implementation type; not the interface.
    QueueStorage.AddToQueue((dynamic)itemToQueue);
}

With QueueStorage being a dependency that implements IQueueStorage. I wish to unit test it but the (dynamic) keyword seems to be blocking Moq from binding correctly to it. The keyword is used to correctly assign the concrete class type rather than ICommand interface type when it is added to the queue.

The unit test looks like this:

[Test]
public void Enqueue_ItemGiven_AddToQueueCalledOnQueueStorage()
{
    int timesAddToQueueCalled = 0;

    var dummyQueueStorage = new Mock<IQueueStorage>();
    var testCommand = new TestCommand();

    var queueManager = new AzureCommandQueueManager();

    dummyQueueStorage
        .Setup(x => x.AddToQueue(It.IsAny<TestCommand>()))
        .Callback(() => timesAddToQueueCalled++);

    queueManager.QueueStorage = dummyQueueStorage.Object;

    queueManager.Enqueue(testCommand);

    Assert.AreEqual(1, timesAddToQueueCalled);
}

Whilst test command is a blank implementation of ICommand:

private class TestCommand : ICommand
{
}

public interface ICommand
{
}

The timesAddedToQueuCalled is not being incremented. I've tried using It.IsAny<ICommand> and (testCommand) to no avail. It looks like the Callback method is not being executed. Can anyone see what I'm doing wrong?

EDIT: IQueueStorage code:

public interface IQueueStorage
{
    void AddToQueue<T>(T item) where T : class;

    T ReadFromQueue<T>() where T : class;
}
9
  • I fail to see whu you need the dynamic at all. Why does it matter whether the type of the parameter of AddToQueue() is an interface or not? The actual type cannot be the interface anyway Commented May 16, 2012 at 12:21
  • Code you provided works fine. Do you have several overloaded AddToQueue methods in IQueueStorage? Commented May 16, 2012 at 12:22
  • @Attila I am using Azure queue storage; if you are using XMLSerializer alongside a generic method it needs to know what it's serializing to the queue. Commented May 16, 2012 at 12:24
  • @lazyberezovsky Single AddToQueue method in IQueueStorage. I'll add the AddToQueue signature to the question Commented May 16, 2012 at 12:26
  • @Click-Rex are you using It.IsAny<TestCommand>()? Check maybe there something like It.IsAny<ICommand>() Commented May 16, 2012 at 12:31

1 Answer 1

2

Here is code which works without problems:

public class AzureCommandQueueManager
{
    public void Enqueue(ICommand itemToQueue)
    {
        if (itemToQueue == null)            
            throw new ArgumentNullException("itemToQueue");

        QueueStorage.AddToQueue((dynamic)itemToQueue);
    }

    public IQueueStorage QueueStorage { get; set; }
}

public interface IQueueStorage
{
    void AddToQueue<T>(T command) where T : class;        
}

public class TestCommand : ICommand  {}

public interface ICommand {}

And test method:

[Test]
public void Enqueue_ItemGiven_AddToQueueCalledOnQueueStorage()
{
    int timesAddToQueueCalled = 0;

    var dummyQueueStorage = new Mock<IQueueStorage>();
    var testCommand = new TestCommand();

    var queueManager = new AzureCommandQueueManager();

    dummyQueueStorage
        .Setup(x => x.AddToQueue(It.IsAny<TestCommand>()))
        .Callback(() => timesAddToQueueCalled++);

    queueManager.QueueStorage = dummyQueueStorage.Object;

    queueManager.Enqueue(testCommand);

    Assert.AreEqual(1, timesAddToQueueCalled);
}

The only difference I see - you have private modifier of TestCommand class. Btw if it is private, how do you access that class from your tests?

Sign up to request clarification or add additional context in comments.

2 Comments

The class is embedded inside the Test class
My god; it was the private modifier; making it public means the AzureCommandQueueManager can read it. Thank you for the help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.