Why I am not getting a pass on my unit test

0

I have some code:

public class ProcessManager : IProcessManager
{
private readonly IFolderWatcher _folderWatcher;
private readonly ILogger _logger;
private readonly Action<string> _action;
private readonly IReadFiles _readFiles;
private readonly IBankStatementComparisonManager _bankStatementComparisonManager;
private readonly IPrepareIncomingBankStatementRecords _prepareIncomingBankStatementRecords;

public ProcessManager(IFolderWatcher folderWatcher, ILogger logger,IReadFiles readFiles, IBankStatementComparisonManager bankStatementComparisonManager, IPrepareIncomingBankStatementRecords prepareIncomingBankStatementRecords)
{
    this._folderWatcher = folderWatcher;
    this._logger = logger;
    this._readFiles = readFiles;
    this._bankStatementComparisonManager = bankStatementComparisonManager;
    this._prepareIncomingBankStatementRecords = prepareIncomingBankStatementRecords;

    _action = ProcessFile;
}

public void Start() { StartMainProcess(); }

private void StartMainProcess()
{
    try
    {
    _folderWatcher.StartFolderWatcher(_action); 
    }
    catch (Exception e)
    {    
    _logger.Error("Failed To Start Folder Watcher.  Shutting Down.");
    _logger.Error("Error Message: " + e.Message);
    _logger.Error("Inner Exception: " + e.InnerException);
    }
}
}

And a test:

    public void Test()
    {
        //Arrange
        var mockFolderWatcher = new Mock<IFolderWatcher>();
        var mockLogger = new Mock<ILogger>();
        var mockRFiles = new Mock<IReadFiles>();
        var mockBankStatementComparisonManager = new Mock<IBankStatementComparisonManager>();
        var mockPrepareIncomingBankStatementRecords = new Mock<IPrepareIncomingBankStatementRecords>();
        var mockAction = new Mock<Action<string>>();

        ProcessManager target = new ProcessManager(mockFolderWatcher.Object, mockLogger.Object, mockRFiles.Object, mockBankStatementComparisonManager.Object, mockPrepareIncomingBankStatementRecords.Object);

        //Act
        target.Start();

        //Assert
        mockFolderWatcher.Verify(m => m.StartFolderWatcher(mockAction.Object), Times.Once());
    }

When I run the test (in debug) I can see that the mockFolderWatcher.Invocations.Count = 1.
However my test fails and I get this error:

Moq.MockException HResult=0x80131500 Message= Expected invocation on the mock once, but was 0 times: m => m.StartFolderWatcher(Action)

So why do I get a fail and the error?

c#
nunit
moq
asked on Stack Overflow Jan 31, 2020 by Richard210363

1 Answer

2

Your assertion:

mockFolderWatcher.Verify(m => m.StartFolderWatcher(mockAction.Object), Times.Once());

Says that StartFolderWatcher must be called with that specific Action (mockAction.Object). This isn't the case: it's called with an Action which was created by the ProcessManager, and which points to its ProcessFile method.

You probably want to say "Verify that StartFolderWatcher was called with any Action":

mockFolderWatcher.Verify(m => m.StartFolderWatcher(It.IsAny<Action<string>>()), Times.Once());

By default, Moq accepts any calls which you haven't set up expectations for (you can change this by specifying MockBehaviour.Strict when you create the mock, if you want). This is why Moq silently accepted the call to StartFolderWatcher that was actually made by the ProcessManager.

You can call mockFolderWatcher.VerifyNoOtherCalls(); to check that no other unexpected calls were made to your mock.

answered on Stack Overflow Jan 31, 2020 by canton7 • edited Jan 31, 2020 by canton7

User contributions licensed under CC BY-SA 3.0