Moq.Dapper icon indicating copy to clipboard operation
Moq.Dapper copied to clipboard

Ability to Mock Multiple Dapper Calls at a Time

Open steventmayer opened this issue 7 years ago • 11 comments

I am attempting to test a feature that relies on multiple QueryAsync<T>; however, when apply the second setup, it overrides the first mock setup, even if T is different. I was hoping that it would work differently for different T's or by changing the SQL statement, but no luck. Code looks like this.

var mock = new Mock<IDbConnection>(); mock.SetupDapperAsync(c => c.QueryAsync<T1>(It.IsAny(), null, null, null, null)).ReturnsAsync(object1); mock.SetupDapperAsync(c => c.QueryAsync<T2>(It.IsAny(), null, null, null, null)).ReturnsAsync(object2);

var expected = object1; var actual = mock.Object.Query<T1>("", null, null, null, null).ToList(); // shows up as Object2.

I'll ask on SO to see if I'm missing something. Thanks for this great library.

steventmayer avatar Oct 15 '18 22:10 steventmayer

Hi @steventmayer, I may have some time in December to look at this, from a first glance at the specs, I would check the behaviour of Moq in this case, I have a feeling that it overrides the previous setup, too. One way to get around this would be to add a SetupSequence which I think may be not so difficult to implement and you would be able to setup multiple objects to return.

UnoSD avatar Oct 28 '18 14:10 UnoSD

Let me try playing around with SetupSequence . One area I was looking at was the ability to limit it if I declared the SQL ( c.QueryAsync("SP.StoredProcName" above instead) but need to look further into expressions. If I'm able to get something working, I'll put a PR in and see if you're interested.

steventmayer avatar Oct 29 '18 03:10 steventmayer

Thanks, I'll do my best to find some time to look at the PR as soon as possible.

UnoSD avatar Oct 29 '18 11:10 UnoSD

Let me try playing around with SetupSequence . One area I was looking at was the ability to limit it if I declared the SQL ( c.QueryAsync("SP.StoredProcName" above instead) but need to look further into expressions. If I'm able to get something working, I'll put a PR in and see if you're interested.

@steventmayer

Do you mind if I ask for a simple sample?

shahabganji avatar May 15 '19 13:05 shahabganji

@steventmayer @UnoSD @shahabganji

Did this get resolved?

kaijday avatar Apr 17 '20 12:04 kaijday

@steventmayer @UnoSD would like an update on the status of this if possible.

Thanks

IanKeefer avatar May 21 '20 13:05 IanKeefer

Is there a solution to this yet?

hampton1122 avatar Oct 09 '20 15:10 hampton1122

Is there a solution to this yet?

I haven't ran into one myself and our unfortunate result so far is omitting the functions from code coverage.

Looks as if this repo is finished as the owner hasn't been active here or on GitHub in a long time.

IanKeefer avatar Oct 09 '20 15:10 IanKeefer

        [Test]
        public void Callback()
        {
            var connection = new Mock<IDbConnection>();

            int[] firstExpected = { 15 };
            int[] secondExpected = { 20 };

            IEnumerable<int> expected = firstExpected;

            connection.SetupDapper(x => x.Query<int>(It.IsAny<string>(), null, null, true, null, null))
                      .Returns(() => expected)
                      .Callback(() => expected = secondExpected);

            var firstActual = connection.Object.Query<int>("");
            Assert.That(firstActual, Is.EquivalentTo(firstExpected));

            var secondActual = connection.Object.Query<int>("");
            Assert.That(secondActual, Is.EquivalentTo(secondExpected));
        }

this may work as a solution. getting it to work appears to be way more complicated than I thought; it's hard to get the previous return value from Moq even with reflection and the ugly alternative is to keep a dictionary of the mocks and return values. I'm going for the hack, but new problems are bubbling up

UnoSD avatar Jan 29 '22 17:01 UnoSD

Is there any update on this issue please? This hack is not working for me @UnoSD

        _mockIDbConnection
           .SetupDapperAsync(c => c.QueryAsync<ComboDishListModel>(
               It.IsAny<string>(), // You can specify the exact SQL query if needed
               It.IsAny<object>(),  // You can specify the expected parameters if needed
               It.IsAny<IDbTransaction>(),
               It.IsAny<int?>(),
               It.IsAny<CommandType?>()))
           .ReturnsAsync(comboDishListModels); // Provide the expected result

        _mockIDbConnection
.SetupDapperAsync(c => c.QueryAsync<OrderViewModel>(
    It.IsAny<string>(),
    new { command.OrderId, command.UserId },
    It.IsAny<IDbTransaction>(),
    It.IsAny<int?>(),
    It.IsAny<CommandType?>()))
.ReturnsAsync(ordersResult);

When apply the second setup, it overrides the first mock setup, even if T is different

yogeshk97 avatar Jan 07 '24 19:01 yogeshk97

@yogeshk97 at the moment I do not have the capacity for working on the repo, but I welcome PRs and I am happy to review.

UnoSD avatar Jan 08 '24 10:01 UnoSD