moq setup not returning expected value
Asked Answered
F

4

8

i am using Nunit and Autofac's Moq to setup a test

    [TestFixture]
public class SomeTests
{

    [OneTimeSetUp]
    public void Initialize()
    {

    }
    [Test]
    public void SalaryCheck()
    {                              
        using (var mock = AutoMock.GetLoose())
        {
            // Arrange
            mock.Mock<ICommonServices>().Setup(x => x.AddTwoNumbers(1,2)).Returns(5);
            var sut = mock.Create<SomeManager>(); 
            // Act
            int actul = sut.CalculateSalary(1);


            var expected = 5;


            // Assert
            Assert.AreEqual(expected, actul);

        }
    }
}

CalculateSalary function looks like this

  public int CalculateSalary(int hours)
    {
        var addres = _commonService.AddTwoNumbers(5,3);
        if (addres == 5)
        {
            return addres * hours;
        }
        else
        { 
            return  100;
        }
    }

i want AddTwoNumbers function which is a external dependency, to return 5 no matter what. thats why i am setting it up after mocking it. But when i debug this test it looks like it goes inside the calsulate salary function but returns a "0" for AddTwoNumbers function. which is kind of a default or a null value.

it does not return me 5 i.e. what i set it up to return.

Firm answered 21/7, 2016 at 14:33 Comment(0)
D
18

You need to use It.IsAny<int>() i.e.

mock.Mock<ICommonServices>().Setup(x => x.AddTwoNumbers(It.IsAny<int>(),It.IsAny<int>())).Returns(5);
Depart answered 21/7, 2016 at 14:42 Comment(0)
C
7

When mocking a method that returns an abstraction, make sure that the type in your call to It.IsAny< YourType >() actually matches the type of the param of the method you are mocking.

Given a method that takes an IEnumerable as a param:

interface IQueueItemRepository {
  IQueueItem GetFirstNotIn(IEnumerable<Guid> guids)
}

In the example below, the .Setup will only ever be invoked when .GetFirstNotIn is called with a Collection as param.

Mock<IQueueItemRepository> queueMock = new Mock<IQueueItemRepository>();

queueMock
    .Setup(x => x.GetFirstNotIn(It.IsAny<Collection<Guid>>()))
    .Returns(new QueueItem());

In other words, if the code you are testing never calls .GetFirstNotIn with a Collection, your .Setup will never be invoked. It may be called numerously throughout your code with an IEnumerable as param, but those calls do not match the .Setup.

So be sure to match your param types to your .Setup types:

Mock<IQueueItemRepository> queueMock = new Mock<IQueueItemRepository>();

queueMock
    .Setup(x => x.GetFirstNotIn(It.IsAny<IEnumerable<Guid>>()))
    .Returns(new QueueItem());
Corbeil answered 12/11, 2018 at 11:4 Comment(1)
I debugged one test for almost 3 hours straight... only to find out after reading this answer, that I have nullable param in the method (in test I passed standard param).Thanks! :)Wellestablished
D
0

In addition to what the other answers point out, I would like to mention that you apparently need to match all of the setup criteria for Returns to even run. I had a setup to the following effect:

myRetriever.Setup(ar => ar.GetEvents(It.IsNotNull<HttpClient>(), It.Is<FilterCriteria>(s => validate(s)))).Returns(Task.FromResult(new List<MyClass>
                {
                    new MyClass
                    {
                        // ...
                    }
                })).Verifiable();

However, validate(s) returned false, so Returns never ran. Unfortunately, this resulted in the test failing due to a Null Pointer Exception (rather than due to the fact that the criteria listed in Setup weren't met).

Drambuie answered 8/5, 2023 at 16:18 Comment(0)
I
0

Ensure careful consideration of when and where you invoke your setup method. For instance, if you have a class dependent on a mock object, calling the setup method within the constructor might lead to unexpected outcomes. To address this issue, refactor your test to pass the mock object, along with the setup method, to the constructor. See the code example below for clarification:

 public ClassWithDependecy(ISettingsProvider settingsProvider)
 {
     // expecting "Test" value for tests
     var expectedTest = settingsProvider.GetAppSetting("settings");
 }


 [Theory, AutoMockData]
 public void IncorectTest([Frozen] Mock<ISettingsProvider> settingsProvider, ClassWithDependecy classWithDependency)
 {
     // Will never be called - ClassWithDependecy is initialized with unexpected value
     settingsProvider.Setup(sp => sp.GetAppSetting(It.IsAny<string>())).Returns("Test");
     // test code
 }

 [Theory, AutoMockData]
 public void CorectTest([Frozen] Mock<ISettingsProvider> settingsProvider)
 {
     // Works fine
     settingsProvider.Setup(sp => sp.GetAppSetting(It.IsAny<string>())).Returns("Test");
     var classWithDependecy = new ClassWithDependecy(settingsProvider.Object);
     // test code
 }
Imbecility answered 15/3 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.