2013-07-04 7 views
11

Mam projekt ASP.NET MVC4 Web API z kontrolerem dziedziczącym ApiController, który akceptuje parametr ODataQueryOptions jako jeden z jego nakłady.Utworzenie nowego System.Web.Http.OData.Query.ODataQueryOptions w skrytce testowej kontrolera ASP.NET Web API

Używam NUnit i Moq do przetestowania projektu, który pozwala mi ustawić odpowiedzi w puszkach z odpowiednich metod repozytoriów używanych przez ApiController. To działa, jak w:

[TestFixture] 
public class ProjectControllerTests 
{ 
    [Test] 
    public async Task GetById() 
    { 
     var repo = new Mock<IManagementQuery>(); 

     repo.Setup(a => a.GetProjectById(2)).Returns(Task.FromResult<Project>(new Project() 
     { 
       ProjectID = 2, ProjectName = "Test project", ProjectClient = 3 
     })); 

     var controller = new ProjectController(repo.Object); 
     var response = await controller.Get(2); 

     Assert.AreEqual(response.id, 2); 
     Assert.AreEqual(response.name, "Test project"); 
     Assert.AreEqual(response.clientId, 3); 
    } 
} 

Wyzwaniem mam to, że aby korzystać z tego wzoru, muszę przejść w odpowiednich parametrów kwerendy do sterownika, a także repozytorium (to był faktycznie mój zamiar). Jednak w przypadku akceptowania przez ODataQueryOptions metod ApiController, nawet w przypadkach, w których chciałbym użyć tylko domyślnych parametrów ODataQueryOptions, muszę wiedzieć, jak je utworzyć. To staje się trudne:

  • ODataQueryOptions nie implementuje interfejsu, więc nie mogę z niego bezpośrednio drwić.
  • Konstruktor wymaga implementacji System.Web.Http.OData.ODataQueryContext, co wymaga implementacji czegoś implementującego Microsoft.Data.Edm.IEdmModel, dla którego brakuje dokumentacji, a Visual Studio 2012 Find References i View Hierarchy połączeń nie dostarczaj wglądu (co implementuje ten interfejs?).

Co muszę zrobić/Czy jest lepszy sposób na zrobienie tego?

Dzięki.

Odpowiedz

6

Wygląda jak ktoś już odpowiedział ten w komentarzach here, ale nie jest to kompletne rozwiązanie dla mojego przypadków użycia (patrz komentarz poniżej):

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntitySet<Customer>("Customers"); 
var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)), request); 
+2

Cóż, ponieważ mój EntitySet pochodzi od modelu EntityFramework i są w dużej mierze związane z nimi obiekty, wydaje się, że trzeba zapewnić EntitySet <> dla każdego TEntity w moim objectcontext ... czy to prawda? Musi być jakiś sposób, aby przejść od objectcontext => odataqueryoptions, prawda? – user483679

0

Jest to rozwiązanie, które były używane w moim NUnit testuje wstrzyknąć ODataQueryOptions

private static IEdmModel _model; 
private static IEdmModel Model 
{ 
    get 
    { 
     if (_model == null) 
     { 
      var builder = new ODataConventionModelBuilder(); 

      var baseType = typeof(MyDbContext); 
      var sets = baseType.GetProperties().Where(c => c.PropertyType.IsGenericType && c.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)); 
      var entitySetMethod = builder.GetType().GetMethod("EntitySet"); 
      foreach (var set in sets) 
      { 
       var genericMethod = entitySetMethod.MakeGenericMethod(set.PropertyType.GetGenericArguments()); 
       genericMethod.Invoke(builder, new object[] { set.Name }); 
      } 

      _model = builder.GetEdmModel(); 
     } 

     return _model; 
    } 
} 

public static ODataQueryOptions<T> QueryOptions<T>(string query = null) 
{ 
    query = query ?? ""; 
    var url = "http://localhost/Test?" + query; 
    var request = new HttpRequestMessage(HttpMethod.Get, url); 
    return new ODataQueryOptions<T>(new ODataQueryContext(Model, typeof(T)), request); 
} 
Powiązane problemy