views:

251

answers:

3

Hi! I'm starting to use Moq and I cannot figure out how to test the method Execute in the code below:

I have the following class:

public class MyObject {
    private IDataReaderPlugin m_source;
    private IDataWriterPlugin m_dest;
    private string[] m_dummyTags = new string[] { "tag1", "tag2", "tag3"};

    public void Execute(DateTime time)
    {
        DataCollection tags = m_source.SnapshotUtc(m_dummyTags, time);

        //Doing some treatment on the values in tags    

        m_dest.Write(tags); 
    }

}

Another method is responsible to create and initialize IDataReaderPlugin and IDataWriterPlugin from information in a configuration file.

I want to test the method Execute. So, I need to mock m_source and m_dest and after I want to test the result sent to m_dest.

How I can achieve this with Moq?

Thanks.

+2  A: 

"Another method is responsible" - this is the crucial bit of information. If you are using an IoC or DI framework then you'll need to insert some Moq mocks of the interfaces IDataReaderPlugin and IDataWriterPlugin. Then the Execute method will use these mocks supplied by the IoC/DI framework.

If they are simply set by a setter or property then it's as simple as:

// Arrange
var mo = new MyObject();
var srcMock = new Mock<IDataReaderPlugin>();
src.Setup(src => src.SnapshotUtc(It.IsAny<string[]>(), It.IsAny<DateTime>()))
   .Returns(new DataCollection() /* or whatever */);
mo.SetSource(srcMock.Object);
// ... same for m_dest
// Act
mo.Execute(DateTime.Now);
// Assert
// assert something... srcMock.Verify() or whatever
thatismatt
Unfortunately, how the class is designed, the 2 interfaces are created inside the class so I cannot inject the mocked interfaces.
Francis B.
+2  A: 

This should get you started:

DateTime myDate = DateTime.Now;

DataCollection tags = new DataCollection();

Mock<IDataReaderPlugin> dataReaderPlugin = new Mock<IDataWriterPlugin>();
dataReaderPlugin.Setup(drp => drp.SnapshotUtc(It.IsAny<string[]>(), myDate)).Returns(tags);

Mock<IDataWriterPlugin> dataWriterPlugin = new Mock<IDataWriterPlugin>();
dataWriterPlugin.Setup(dwp => dwp.Write(tags);    

MyObject mo = new MyObject();
mo.Execute();

mock.Verify(foo => foo.Write(tags));
rball
As far as I know, you can't actually do It.IsAny<string[]>()... I've never found a great way around this :/
womp
Yeah, the answer was from my memory. You should be able to create a dummy string[] and then pass that in.
rball
+4  A: 
[Test]
public void ShouldWriteToMDest()
{
   // Arrange
   var mockDest = new Mock<IDataWriterPlugin>();
   var mockSource = new Mock<IDataReaderPlugin>();
   string[] m_dummyTags = new string[] { "tag1", "tag2", "tag3"};

   mockSource.Setup(source => source.SnapshotUtc(m_dummyTags, It.IsAny<DateTime>()).Returns(/*whatever you need*/);

   var myObj = new MyObject(mockSource.Object, mockDest.Object);

   // Act
   myObj.Execute(DateTime.Now);


   // Assert
   Assert.That(mockSource.Object.WhateverPropertyContainsOutput == /*Whatever you need */);

}
womp
As it stands, unless you can inject your interface classes into your MyClass, it's untestable anyway, since your class will be creating them. You need to use a constructor like what I've shown in my code example to inject the dependencies.
womp