13

I have a simple method I am testing. When I run the test I get the error

"All invocation on the mock must have a corresponding setup"

on the last line

dataField.DefaultValue = orderNumber.ToString();

What would cause this?

I am just setting a field.

void IUtilities.SetOrderIdInDocumentMetaData(Document document, int orderNumber)
{
    DataField dataField = null;
    if (document.DataFields.IsPresent(ORDER_ID) == false)
    {
        dataField = document.DataFields.Add(ORDER_ID, AppDefault: false, DocDefault: false);
    }
    else
    {
        dataField = document.DataFields[ORDER_ID];
    }

    dataField.DefaultValue = orderNumber.ToString();
}

This is my unit test code.

[TestMethod]
public void Utilities_SetOrderIdInDocumentMetaData_SetNew()
        {
    string orderNumber = "1";
    int orderId = 1;

    corelDocument
        .Setup(s => s.DataFields.IsPresent(ORDER_ID))
        .Returns(false);

    corelDocument
        .Setup(s => s.DataFields.Add(ORDER_ID, null, false, false, false))
        .Returns(corelDataField.Object);

    corelDataField
        .Setup(s => s.DefaultValue)
        .Returns(orderNumber);

    Utilities.SetOrderIdInDocumentMetaData(corelDocument.Object, orderId);

    Assert.AreEqual(orderNumber, corelDataField.Object.DefaultValue);
}
Old Fox
  • 8,629
  • 4
  • 34
  • 52
Ben Hoffman
  • 8,149
  • 8
  • 44
  • 71

3 Answers3

8

If you want the mock's properties to retain assigned values, call SetupAllProperties

corelDataField.SetupAllProperties();

Your initial setup

corelDataField
    .Setup(s => s.DefaultValue)
    .Returns(orderNumber);

was only for getting the value, not setting it.

When you call

dataField.DefaultValue = orderNumber.ToString();

You are trying to set the property. Which the mock was not setup to handle.

Reference : Moq Quickstart

Nkosi
  • 235,767
  • 35
  • 427
  • 472
6

You are using a "Strict Mock" which is count as bad practice(except rare cases). The reason it is a bad practice is quite simple; Your UT became too depends on the implementation instead of verifying behavior of specific case.

Just remove MockBehavior.Strict from the mock initialization and then everything will work fine.

Old Fox
  • 8,629
  • 4
  • 34
  • 52
  • 8
    This is a subjective answer (it's often not bad practice) that doesn't explain the implications of turning this off. Yes it might fix the problem but is a sledgehammer solution and you should understand what you are giving up when doing it. – Stuart Dobson Mar 04 '20 at 00:10
  • 1
    @stuartdotnet strict mock is raising an exception when any call which don't have expectation is being called. when you are using it than usually you test more than one thing and make your UT to not testing only behavior. In most cases over time it will cause you more troubles than help due to the fact that live code is changing and the UT will fall although the behavior wasn't change and without it you weren't touch your UT at all. This is usually where companies who tried UTs for the first time fall. – Old Fox Aug 27 '20 at 17:40
0

I have the following interface.

public interface IEventGridTopic
{
  Task PublishCompanyOnboarding(string companyName);
}

I have setup the Moq like this.

eventGridTopicMock.Setup(eventGridTopic => eventGridTopic.PublishCompanyOnboarding(It.IsAny<string>()));

Now I get the following message as the test fails.

IEventGridTopic.PublishCompanyOnboarding("asdfasdf") invocation failed with mock behavior Strict. Invocation needs to return a value and therefore must have a corresponding setup that provides it.

So return value is not configured. I did not configure it as I thought its returning Task, means void, nothing.

So I changed it to the following to make it pass.

eventGridTopicMock.Setup(eventGridTopic => eventGridTopic.PublishCompanyOnboarding(It.IsAny<string>())).Returns(Task.CompletedTask);

Add Returns(Task.CompletedTask)

Reference. Moq with Task await

VivekDev
  • 20,868
  • 27
  • 132
  • 202