1

I'm trying to verify that Delete on my DomainContext has been called with an expression containing a specific value. So, simple contrived example - real code:

DomainContext.Delete<Entity>(x => x.Id == id);

Test code:

DomainContext = new Mock<DomainContext>();
DomainContext.Setup(x => x
    .Delete<Entity>(
        It.Is<System.Linq.Expressions.Expression<Func<Entity, bool>>> 
        (predicate => predicate == x => x.Id == id)
    ).Verifiable();

// act

DomainContext.Verify();

Obviously won't work because it's trying to compare two predicates by reference - and it may not even be evaluating the id variable on one or both sides!

Is there some way I can write a predicate (something like It.HasProperty?!) to replace predicate == x => x.Id == id to check that there is a call to check the predicate was called with Id == the ID I'm expecting?

Ian Grainger
  • 5,148
  • 3
  • 46
  • 72
  • @FCin I may be wrong but I didn't think they were asking the same thing. I'm trying to verify a call has been called with an expression containing a certain value. They're trying to mock a call which takes an expression as a parameter - which I've done with the `It.Is` line (and this works). – Ian Grainger May 30 '18 at 13:03
  • I wonder if an expression comparer would work: https://stackoverflow.com/questions/283537/most-efficient-way-to-test-equality-of-lambda-expressions?noredirect=1&lq=1 - problem is that the expression only needs the correct types - AND for the one constant value to be equal. – Ian Grainger May 30 '18 at 13:06
  • 1
    It seems to me that you're trying to treat code as data. But maybe you could solve the issue by mocking the Entity class and checking that the getter on the Id property has been called? – Hans Kilian May 30 '18 at 13:13
  • @HansKilian maybe I am - but even if I am, shouldn't it be possible to construct a way to check this predicate? Even if it involves reflection - looking inside the predicate? The problem with checking the getter on the entity class is that I'm only checking that it's been 'looked at' not that it was the correct match. – Ian Grainger May 30 '18 at 13:24
  • Am I understanding it correctly that you're not writing a test case but some validation code that you want to run in production on all calls? – Hans Kilian May 30 '18 at 13:39
  • @HansKilian No, a test case. The obvious thing to do instead is to introduce an abstraction so I can mock more easily. But I don't want to :( ! – Ian Grainger May 30 '18 at 13:53
  • If you're in a test case I would think that that is such a controlled environment that if someone is looking at the Id property, then it's doing what you want? – Hans Kilian May 30 '18 at 13:59
  • @HansKilian I think I get what you mean, but I want to check if it's deleting the correct ID. The one that I pass into the system under test. Not just that it's checking IDs in the first place. I've currently left it verifying that the delete function is called with an expression. That's not a terrible test - but checking that the expression checks for the correct ID would obviously be much better. – Ian Grainger May 30 '18 at 14:00
  • I have 2 ideas: 1) Change focus to verifying that your data ends up in a desired end state. I.e. that the data has been deleted from the context. Or 2) Seeing if you can grab the function that is passed to Delete and then calling it with an Entity you expect to be deleted and one you don't expect to be deleted. I.e. where the function returns true / false. – Hans Kilian May 30 '18 at 14:34
  • @HansKilian 1) I don't have a real DB context behind here, so I can't verify the change - I don't think. Unless I can do something in the setup?! 2) I don't have access to the function. I COULD inject it. But ew. Changing the code just for this test - and if I'm going to change it, I could change it to get the CaseId then Delete it (though that would mean 2 DB hits, I think?) – Ian Grainger May 30 '18 at 14:42

0 Answers0