I'm using Moq to write the unit tests for a project, and one of the tests is failing when I try to verify that a DateTime property is assigned a value. Here's my Verify (which fails):
_mockTaskContext.Verify(context => context.TaskQueue.AddObject(It.Is<TaskQueueItem>(
task_queue => task_queue.TaskCode == (int)TaskCode.MyTask
&& task_queue.ClientID == ExpectedClientID
&& task_queue.JobNumber == It.IsAny<int>()
&& task_queue.Requester == String.Empty
&& task_queue.JobStatus == (int)JobStatus.Submitted
&& task_queue.TimeQueued == It.IsAny<DateTime>()
&& task_queue.TimeStarted == new DateTime(1900, 1, 1)
&& task_queue.TimeStopped == new DateTime(1900, 1, 1)
&& task_queue.TaskParameters == expectedTaskParam
If I comment out the expectation on
task_queue.TimeQueued then the test passes, without making any other changes to my test. Also, if I change the requirement on either
new DateTime(1900, 1, 1) to
It.IsAny<DateTime>(), the test fails. I've run the code under test outside the unit test with the actual implementation instead of a mocked repository, and
TimeQueued is being assigned its value correctly. Any idea why
It.IsAny doesn't seem to work correctly for
DateTime properties, or am I setting up my expectations incorrectly?
Update: I'm using It.IsAny() in other tests without any problem, but this test is still failing. I think it might be because this is inside the It.Is lambda expression, but I don't know how I would work around that.
I am sure the
It.IsAny<>() syntax must be used within the scope of the mock object. In this case when you use
Setup and the mock arguments directly. This is because the mock object is in recording mode capturing the values you pass into arguments so
mock.Setup(x => x.Foo(It.IsAny<Bar>()));
will process the arguments when the Setup line is executed.
However in your example you are trying to use
It.IsAny<>() from within the delegate to verify an argument passed in matches. When this occurs the mock is not recording but in the process of being used as a result of the object under test (which is much later).
someValue == It.IsAny<DateTime>() cannot evaluate to true as the return of the
IsAny method must return a matching value for it to be true. I expect that
It.IsAny<int>() also does not work.
My suggestion is that you will have to match either exact values or in this case match a range of dates
&& IsInRange(DateTime.MinValue, DateTime.MaxValue, task_queue.TimeQueued)
IsInRange simply another method you have for checking a value is between 2 min and max bounds.