Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AddRangeAsync xunit .net core error #327

Closed
zaiboot opened this issue Mar 6, 2017 · 4 comments
Closed

AddRangeAsync xunit .net core error #327

zaiboot opened this issue Mar 6, 2017 · 4 comments

Comments

@zaiboot
Copy link

zaiboot commented Mar 6, 2017

Running on:

  • VS2017
  • .net core 1.1
  • moq 4.7.1
  • xunit 2.2.0-beta5-build3474
  • xunit.runner.visualstudio : 2.2.0-beta5-build1225

I have the following code on my repositoryfile.cs

public async Task<int> AddSales(IList<SomeModel> mode)
{
    await Context.DBSet.AddRangeAsync(model);
    return await Context.SaveChangesAsync();
}

And the following test:

[Fact]
public async void AddSalesTest()
{
    var expected = 1;
    var sales = new List<SomeModel>
    {
        new SomeModel{ ... }
    };
    _context.Setup(c => c.DBSet.AddRangeAsync(It.IsAny<List<SomeModel>>(), It.IsAny<CancellationToken>()));
    _context.Setup(c => c.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(expected);
    var system = GetSystem();
    var actual = await system.AddSales(sales);
    Assert.Equal(expected, actual);
}

Getting the following error:

Message: Moq.MockException : DbSet`1.AddRangeAsync([Reporting.DAL.Models.SomeModel], System.Threading.CancellationToken) invocation failed with mock behavior Strict.
Invocation needs to return a value and therefore must have a corresponding setup that provides it.

Seems like Moq doesnt support mocking Task vs Task<OfSomething>.

Any ideas on this? If you need more info I can set up a git repo to show the error in a more easy way.

Thanks

@stakx
Copy link
Contributor

stakx commented Jun 5, 2017

@zaiboot: Your code won't compile since it's incomplete so it's hard to reproduce your issue, but I guess this part of the error message is a sufficient hint at what is going wrong here:

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

This tells you that the first of your two setups (the one involving AddRangeAsync) is incomplete; it is lacking a .Returns. As I understand it, MockBehavior.Strict requires every .Setup to have a .Returns:

_context.Setup(c => c.DBSet.AddRangeAsync(It.IsAny<List<SomeModel>>(), It.IsAny<CancellationToken>()));

If you add a .Returns(…), the error should go away:

_context.Setup(c => c.DBSet.AddRangeAsync())
        .Returns((List<SomeModel> _, CancellationToken __) => Task.FromResult(true));

(Tried this the latest version of Moq, which is 4.7.25.)

@stakx
Copy link
Contributor

stakx commented Jun 5, 2017

I do wonder, though, whether there should be a .SetupAsync(Expression<Func<T, Task>>) that doesn't require a .Returns.

  • On the one hand, for methods returning a value there must be a .Returns — and async methods (should) return a Task...
  • On the other hand, methods returning Task are really the asynchronous counterpart to void methods, and those do not require a .Returns.

@stakx
Copy link
Contributor

stakx commented Jun 21, 2017

I am closing this for now, since we have no working repro code and the reported error is quite possibly due to incorrect usage (see this comment further above).

Regarding my previous comment just above, I think this would be better tracked in #384.

@zaiboot: If the above does not help you, please report back and we take another look at your issue.

@stakx
Copy link
Contributor

stakx commented Dec 28, 2017

This is quite likely a minimal repro code example for this issue:

public interface IFoo
{
    Task DoAsync();
}

var mock = new Mock<IFoo>(MockBehavior.Strict);
mock.Setup(m => m.DoAsync());
await mock.Object.DoAsync();

As noted above, one could argue that there should be a Mock<T>.SetupAsync(Expression<Func<T, Task>>) method such that async methods can be set up without specifying .Returns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants