Jak korzystać z Moq i DbFunctions w testach jednostkowych, aby zapobiec NotSupportedException?
Obecnie próbuję uruchomić niektóre testy jednostkowe dla zapytania uruchamianego przez Entity Framework. Samo zapytanie działa bez żadnych problemów w wersji na żywo, ale testy jednostkowe zawsze kończą się niepowodzeniem.
Zawęziłem to do mojego użycia DbFunctions.TruncateTime, ale nie wiem, jak to obejść, aby uzyskać testy jednostkowe odzwierciedlające to, co dzieje się na serwerze na żywo.
Oto metoda, której używam:
public System.Data.DataTable GetLinkedUsers(int parentUserId)
{
var today = DateTime.Now.Date;
var query = from up in DB.par_UserPlacement
where up.MentorId == mentorUserId
&& DbFunctions.TruncateTime(today) >= DbFunctions.TruncateTime(up.StartDate)
&& DbFunctions.TruncateTime(today) <= DbFunctions.TruncateTime(up.EndDate)
select new
{
up.UserPlacementId,
up.Users.UserId,
up.Users.FirstName,
up.Users.LastName,
up.Placements.PlacementId,
up.Placements.PlacementName,
up.StartDate,
up.EndDate,
};
query = query.OrderBy(up => up.EndDate);
return this.RunQueryToDataTable(query);
}
Jeśli skomentuję wiersze z DbFunctions w, wszystkie testy przebiegają pomyślnie (z wyjątkiem tych, które sprawdzają, czy uruchamiane są tylko prawidłowe wyniki dla danej daty).
Czy jest jakiś sposób, aby udostępnić fałszywą wersję DbFunctions.TruncateTime do użycia w tych testach? Zasadniczo powinien po prostu zwracać Datetime.Date, ale nie jest to dostępne w zapytaniach EF.
Edytować: Oto test, który kończy się niepowodzeniem i wykorzystuje sprawdzenie daty:
[TestMethod]
public void CanOnlyGetCurrentLinkedUsers()
{
var up = new List<par_UserPlacement>
{
this.UserPlacementFactory(1, 2, 1), // Create a user placement that is current
this.UserPlacementFactory(1, 3, 2, false) // Create a user placement that is not current
}.AsQueryable();
var set = DLTestHelper.GetMockSet<par_UserPlacement>(up);
var context = DLTestHelper.Context;
context.Setup(c => c.par_UserPlacement).Returns(set.Object);
var getter = DLTestHelper.New<LinqUserGetLinkedUsersForParentUser>(context.Object);
var output = getter.GetLinkedUsers(1);
var users = new List<User>();
output.ProcessDataTable((DataRow row) => students.Add(new UserStudent(row)));
Assert.AreEqual(1, users.Count);
Assert.AreEqual(2, users[0].UserId);
}
Edycja 2: Oto komunikat i ślad debugowania z danego testu:
Test Result: Failed
Message: Assert.AreEqual failed. Expected:<1>. Actual:<0>
Debug Trace: This function can only be invoked from LINQ to Entities
Z tego, co przeczytałem, dzieje się tak, ponieważ nie ma implementacji LINQ do Encji tej metody, która mogłaby zostać użyta w tym miejscu do testu jednostkowego, chociaż jest dostępna w wersji na żywo (ponieważ wysyła zapytanie do serwera SQL).