I am trying to mock result from my repository method so prototype of method looks like:
public IReadOnlyCollection<TResult>> Get<TResult>(IEnumerable<int> ids, Func<Model, TResult> getValues)
and execution would be:
Get<Model>(new [] { 5, 8 }, data => new { data.TimeStamp, data.Value})
What it means it gets me the record from DB and return them in a object form like TResult
. If I want for example timestamp and value from table I will get just that ignoring other column Something like:
IReadOnlyCollection<{DateTime TimeStamp, double? Value}>>
Problem is I can not change this because I am not the owner of that code, so I need to figure it out how to mock it on my own. Owner uses dapper but it will have no meaning here I think.
So I try to mock this operation using Moq:
var mock = new Mock<IModel>(MockBehavior.Strict);
mock.Setup(
value => value.Get(It.IsAny<int[]>(), It.IsAny<Func<Model, object>>()))
.Returns((int _, Func<Model, object> _) =>
Task.FromResult(new[] { _mockValue } as IReadOnlyCollection<object>));
And _mockModel is simple:
private readonly object _mockModel = new
{
Value= 3_000_000,
TimeStamp = DateTime.Parse("2022-12-12T16:00:00"),
};
And result is an exception:
Model.Get<{DateTime TimeStamp, double? Value}>(IEnumerable, Func<Model, {DateTime TimeStamp, double? Value}>) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.
Now what am I missing here?
As it is mentioned in comments I did not found a solution in the way I presented my problem. But I solved it, as this selector is:
Func<Model, TResult> getValues
I basically can put anything that gives me result, so instead of returning it as a anonymous object I can use some value type line named tuple so it would look like:
Get<Model>(new [] { 5, 8 }, data => (data.Timestamp, data.Value))
And result will be the same data as I would use anonymous assembly object.