Reputation: 454
I mocked FindAsync by the following code:
var brands = new Mock<DbSet<Brand>>();
ConfigureTheDbSet(brands, brandData);
brands.Setup(b => b.FindAsync(It.IsAny<object[]>())) //substitution of the .SelectAsync(id) method
.Returns<object[]>(ids => brands.Object.FirstOrDefaultAsync(b => b.BrandId == (int) ids[0]));
and it had been working correctly until I added mocking for AsNoTracking to context:
var mockContext = new Mock<ReportDbContext>();
mockContext.Setup(m => m.Set<Brand>()).Returns(brands.Object);
mockContext.Setup(m => m.Set<Brand>().AsNoTracking()).Returns(brands.Object);
And FindAsync returns null. To make it work i added the following mocking:
mockContext.Setup(m => m.Set<Brand>().FindAsync(It.IsAny<object[]>()))
.Returns<object[]>(async d => await brands.Object.FindAsync(d));
Anybody have a clue why this is happening?
Upvotes: 5
Views: 5686
Reputation: 31
For anyone struggling with this, here's another way of doing it:
First: Create a mock of the DbContext and the DbSet, ex:
private static readonly Mock<ApplicationDbContext> mockDbContext = new();
private static readonly Mock<DbSet<Game>> mockGameSet = new();
Second: Setup the Get of the DbSet in the Mocked DbContext, like this:
mockDbContext.SetupGet(_ => _.Games).Returns(mockGameSet.Object);
Third, and Last: Setup the FindAsync() in the mocked DbSet like this:
mockGameSet.Setup(x => x.FindAsync(It.IsAny<int>())).ReturnsAsync(game);
Upvotes: 2
Reputation: 992
I circumvented this mocking by using .Where(entity => entity.PrimaryKey == key).FirstOrDefaultAsync()
in place of .FindAsync(key)
as FirstOrDefaultAsync
did not require a separate mocking and logic is also same between both approaches
Upvotes: 0
Reputation: 25
Dimitry, I know that it's been a couple of years. I just had the same issue and this is what I did to get it to work
this.mocContext.Setup(x => x.Company.FindAsync(It.IsAny<string>
())).Returns(Task.FromResult(this.GetCompanyList().SingleOrDefault(x =>
x.CompanyCode.Equals("M5QoKF4AS0"))));
Here mocContext is my Moq'd Database, Company is the table that I want to perform the FindAsync on, the Get CompanyList just pulls from the data the populated the table. Hopefully this helps
Upvotes: 1
Reputation: 2317
IMO, you should be mocking interfaces, for example IBrandRepository. Otherwise whats the point of mocking? - you could just create an instance of your class, call FindAsync() and assert the result as usual..
Here is how I use Moq with interfaces, for example a repo interface;
// arrange
var mockRepo = new Mock<IBrandRepository>();
mockRepo.Setup(o => o.FindAsync(It.IsAny<string>())).ReturnsAsync(new Brand[] { ... });
var someClass = new SomeClass(IBrandRepository); // someClass that use IBrandRepository
// act
string search = "brand1 brand2"; // what the user searches for
var results = someClass.FindBrands(searchText) // internally calls IBrandRepository.FindAsync()
// assert
// Assert.AreEqual(results.Count(), ...
Upvotes: 4