2016-11-21 2 views
0

Ich fragte mich, ob es irgendeinen anderen Weg gibt, als einen Wrapper zu bauen, um den FormSql zu verspotten? Ich weiß, dass diese Methode statisch ist, aber da sie Entity Framework Core um Dinge wie AddEntityFrameworkInMemoryDatabase ergänzt haben, dachte ich, dass es auch eine Lösung dafür geben könnte. Ich verwende EF Core 1.0.1 in meinem Projekt.FromSql im Entity-Framework-Core verspotten?

Mein Endziel ist es, diese Methode zu testen:

public List<Models.ClosestLocation> Handle(ClosestLocationsQuery message) 
    { 
     return _context.ClosestLocations.FromSql(
      "EXEC GetClosestLocations {0}, {1}, {2}, {3}", 
      message.LocationQuery.Latitude, 
      message.LocationQuery.Longitude, 
      message.LocationQuery.MaxRecordsToReturn ?? 10, 
      message.LocationQuery.Distance ?? 10 
     ).ToList(); 
    } 

ich sicherstellen möchten, dass meine Abfrage mit dem gleichen Objekt behandelt wird, das ich hineingeben, basierend auf this answer in Entity Framework 6 ich könnte etwas tun dies wie:

[Fact] 
    public void HandleInvokesGetClosestLocationsWithCorrectData() 
    { 
     var message = new ClosestLocationsQuery 
     { 
      LocationQuery = 
       new LocationQuery {Distance = 1, Latitude = 1.165, Longitude = 1.546, MaxRecordsToReturn = 1} 
     }; 

     var dbSetMock = new Mock<DbSet<Models.ClosestLocation>>(); 

     dbSetMock.Setup(m => m.FromSql(It.IsAny<string>(), message)) 
      .Returns(It.IsAny<IQueryable<Models.ClosestLocation>>()); 

     var contextMock = new Mock<AllReadyContext>(); 

     contextMock.Setup(c => c.Set<Models.ClosestLocation>()).Returns(dbSetMock.Object); 

     var sut = new ClosestLocationsQueryHandler(contextMock.Object); 
     var results = sut.Handle(message); 

     contextMock.Verify(x => x.ClosestLocations.FromSql(It.IsAny<string>(), It.Is<ClosestLocationsQuery>(y => 
      y.LocationQuery.Distance == message.LocationQuery.Distance && 
      y.LocationQuery.Latitude == message.LocationQuery.Latitude && 
      y.LocationQuery.Longitude == message.LocationQuery.Longitude && 
      y.LocationQuery.MaxRecordsToReturn == message.LocationQuery.MaxRecordsToReturn))); 
    } 

Aber im Gegensatz zu SqlQuery<T> in EF 6 ist die FormSql<T> in EF-Core statische Erweiterung Methode, ich stelle diese Frage, weil ich glaube, ich könnte dieses Problem aus dem falschen Winkel nähern oder es könnte sein, eine bessere Alternative als ein Wrapper, würde ich mich über jeden Gedanken darüber freuen.

+0

intern die EF Kern [FromSql Erweiterungsmethode] (https://github.com/aspnet/EntityFramework/blob/1fa247b038927a7d7438f666dc11253f64e0432d/src/Microsoft.EntityFrameworkCore.Relational/RelationalQueryableExtensions.cs) einen Anruf an 'CreateQuery' macht on der 'IQueriable.Provider', den Sie sich ansehen könnten, um das zu erreichen, was Sie wollen. – Nkosi

Antwort

1

Wenn Sie sich den Code in FromSql<T> ansehen, können Sie sehen, dass es einen Anruf an source.Provider.CreateQuery<TEntity> macht. Das ist es, was Sie verspotten müssen.

In Ihrem Fall, ich glaube, Sie es heraus mit so etwas wie das funktionieren kann:

var mockProvider = new Mock<IQueryProvider>(); 
mockProvider.Setup(s => s.CreateQuery(It.IsAny<MethodCallExpression>())) 
    .Returns(null as IQueryable); 
var mockDbSet = new Mock<DbSet<AllReady.Models.ClosestLocation>>(); 
mockDbSet.As<IQueryable<AllReady.Models.ClosestLocation>>() 
    .Setup(s => s.Provider) 
    .Returns(mockProvider.Object); 
var t = mockDbSet.Object; 
context.ClosestLocations = mockDbSet.Object; 

var sut = new ClosestLocationsQueryHandler(context); 
var results = sut.Handle(message); 

nicht sicher, wie Sie können Verify auf einem MethodCallExpression danach, aber ich nahm an, dass das möglich ist. Alternativ könnte es möglich sein, das generierte SQL zu überprüfen.

Verwandte Themen