You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It was really hard to come up with a descriptive title, so right of the bat .. sorry for that.
But I've come across something that I'm not sure is a bug, or by design. But until I broke it down into a smaller example, I was quite sure it was a bug.
My mockup has a method that clearly has an error (it's not supposed to update all 3) :
publicclassPriceService{privatereadonlyIInventoryService_inventoryService;publicPriceService(IInventoryServiceinventoryService){_inventoryService=inventoryService;}publicasyncTask<Product>UpdateOnlyNewestPrice(List<Product>products){foreach(var p in products.OrderByDescending(o => o.Created).Take(3)){await _inventoryService.UpdateAsync(p);}return products.FirstOrDefault()??new Product();}}
And my test (verify a little funny formed to showcase this issue)
[Fact]publicasync Task MoqMyWord_UpdateService_OnlyCalledOnce(){varproductList=newList<Product>{new(){Price=1,Created= DateTime.UtcNow.AddDays(-1)},new(){Price=2,Created= DateTime.UtcNow.AddDays(-2)},new(){Price=3,Created= DateTime.UtcNow.AddDays(-3)}};Mock<IInventoryService>service=newMock<IInventoryService>();varpriceService=new PriceService(service.Object);await priceService.UpdateOnlyNewestPrice(productList);//For the sake of the argument a silly way to evaluate any price less than 3 is valid//This is only to make sure the test fails.
service.Verify(u => u.UpdateAsync(It.Is<Product>(p => EvaluatePrice(p))),Times.Once);}privateboolEvaluatePrice(Productproduct){
_outputHelper.WriteLine($"product price is {product.Price}");return product.Price <3;}
This test fails as expected, since the service is called 2 times:
If I then make a shitty change to the implementation, and only change a property of an existing object:
I would still expect it to fail with 2 calls to the service, but it fails with no calls to the service. Moq doesn't recognize the change in the object
The text was updated successfully, but these errors were encountered:
Hi @lund76, no worries about the issue title, it's actually quite acurate. This question gets asked a lot (recently e.g. in #1309 and #1187). When Moq records invocations (for later verification), it simply captures the invocation arguments in an object[] array – it does not deep-clone every argument. This means that the usual .NET rules apply: reference types (such as your Product class) are captured by reference, and value types are captured by value (which essentially amounts to a shallow clone). Therefore if the same Product is captured on three invocations, and you change that Product instance over time, this will be reflected in the recorded invocations.
I'm a little early, but... have a happy new year! 🎆
Thanks for the reply. It what pretty sure it was something along those lines.
I've tried searching a bit for the issue, but must have given up to quickly - sorry for that :)
FYI @lund76, I'm likely going to merge #1319 which will provide a new way to solve this issue; see the last code example in the PR's description for an explanation of how this might help.
Hi
It was really hard to come up with a descriptive title, so right of the bat .. sorry for that.
But I've come across something that I'm not sure is a bug, or by design. But until I broke it down into a smaller example, I was quite sure it was a bug.
I've created a repo with democode:
https://github.com/lund76/MoqMyWords
My mockup has a method that clearly has an error (it's not supposed to update all 3) :
And my test (verify a little funny formed to showcase this issue)
This test fails as expected, since the service is called 2 times:
If I then make a shitty change to the implementation, and only change a property of an existing object:
I would still expect it to fail with 2 calls to the service, but it fails with no calls to the service. Moq doesn't recognize the change in the object
The text was updated successfully, but these errors were encountered: