我正在尝试在 .Net OData Web API 上实现单元测试用例。然而,我面临的问题是,我在 Http 请求 URL 中传递过滤器来过滤数据,但收到了与我发送的相同类型的模拟数据。需要助手我错了什么以及哪里错了。
下面是我的代码
这是客户控制器
public class CustomersController : ODataController
{
private readonly ICustomerRepository _repository;
public CustomersController()
{
_repository = new CustomerRepository(new ODataSampleEntities());
}
public CustomersController(ICustomerRepository repository)
{
// this.genericRepository = repository;//new Repository<Customer>();
_repository = repository;
}
[EnableQuery]
public IQueryable<Customer> Get()
{
return _repository.GetAllCustomers();
}
}
客户模型
public partial class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Country { get; set; }
public string Address { get; set; }
}
存储库
public interface ICustomerRepository
{
//IEnumerable<Customer> GetAllCustomers();
IQueryable<Customer> GetAllCustomers();
}
public class CustomerRepository: ICustomerRepository
{
private readonly ODataSampleEntities _context;
public CustomerRepository(ODataSampleEntities context)
{
_context = context;
}
public virtual IQueryable<Customer> GetAllCustomers()
{
return _context.Customers;
}
}
下面是单元测试用例代码
public class CustomerControllerTests
{
[TestMethod]
public void GetAllCustomers_ShouldReturnAllCustomers()
{
// Arrange
var customers = new List<Customer>
{
new Customer { Id = 1, Name = "John", Country = "USA", Address = "USA" },
new Customer { Id = 2, Name = "Sandesh", Country = "India", Address = "Goa India" }
};
var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44395/Customers?$filter=Name eq 'Sandesh' & $top=1");
HttpRouteCollection routes = new HttpRouteCollection();
HttpConfiguration config = new HttpConfiguration(routes) { IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always };
var Customerbuilder = new ODataConventionModelBuilder();
Customerbuilder.EntitySet<Customer>("Customer");
var model = Customerbuilder.GetEdmModel();
// attempting to register at least some non-OData HTTP route doesn't seem to help
routes.MapHttpRoute("Default", "{controller}/{action}");
config.MapODataServiceRoute("odata", "odata", model);
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
config.EnableDependencyInjection();
config.EnsureInitialized();
request.SetConfiguration(config);
ODataQueryContext context = new ODataQueryContext(
model,
typeof(Customer),
new ODataPath(
new Microsoft.OData.UriParser.EntitySetSegment(
model.EntityContainer.FindEntitySet("Customer"))
)
);
var mockRepository = new Mock<ICustomerRepository>();
mockRepository.Setup(r => r.GetAllCustomers()).Returns(customers.AsQueryable());
mockRepository.SetReturnsDefault<IEnumerable<Customer>>(customers.AsQueryable());
// Create the controller
var controller = new CustomersController(mockRepository.Object);
controller.Request = request;
var options = new ODataQueryOptions<Customer>(context, request);
//var response = controller.Get(); //as ViewResult;
// Act
var result = controller.Get();
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(IEnumerable<Customer>));
var contentResult = result;
Assert.IsNotNull(contentResult);
Assert.AreEqual(1, contentResult.Count());
Assert.AreEqual("Sandesh", contentResult.First().Name);
}
}
每次运行单元测试时,即使我通过请求 Url 传递过滤器查询,它也会给我相同的模拟数据。请协助我在 OData Web API 控制器上实现并执行单元测试用例,该控制器将过滤数据并返回响应。
在单元测试代码中,您将模拟存储库设置为始终返回同一组客户,无论请求 URL 中应用的过滤器如何。这就是为什么每次运行单元测试时都会获得相同的模拟数据。
要在单元测试中模拟过滤行为,您需要修改模拟存储库设置以考虑请求 URL 中提供的过滤器参数并相应地返回过滤后的数据。
以下是实现这一目标的方法:
修改您的单元测试方法以在请求 URL 中包含过滤器参数:
[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
// ... (existing code)
// Modify the request URL to include the filter parameter
var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44395/Customers?$filter=Name eq 'Sandesh'&$top=1");
// ... (existing code)
}
更新模拟存储库的设置以返回过滤后的数据:
[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
// ... (existing code)
var customers = new List<Customer>
{
new Customer { Id = 1, Name = "John", Country = "USA", Address = "USA" },
new Customer { Id = 2, Name = "Sandesh", Country = "India", Address = "Goa India" }
};
// Modify the mock repository setup to consider the filter parameter
mockRepository.Setup(r => r.GetAllCustomers())
.Returns((string filter) =>
{
// Implement filtering based on the filter parameter
if (string.IsNullOrEmpty(filter))
{
return customers.AsQueryable(); // Return all customers if no filter
}
else
{
// Parse the filter and apply it to the customer list
var odataQuery = new ODataQueryOptions<Customer>(
new ODataQueryContext(model, typeof(Customer)),
request
);
var filteredCustomers = odataQuery.ApplyTo(customers.AsQueryable());
return filteredCustomers as IQueryable<Customer>;
}
});
// ... (existing code)
}
通过此设置,模拟存储库现在会将请求 URL 中指定的过滤器应用于客户列表,并在您调用
controller.Get()
时相应地返回过滤后的数据。这应该使您能够正确测试 OData Web API 控制器的过滤行为。
我稍微修改了@Saeed Gholamzadeh 建议的答案,它起作用了。
[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
// ... (existing code)
var customers = new List<Customer>
{
new Customer { Id = 1, Name = "John", Country = "USA", Address = "USA" },
new Customer { Id = 2, Name = "Sandesh", Country = "India", Address = "Goa India" }
};
// Modify the mock repository setup to consider the filter parameter
mockRepository.Setup(r => r.GetAllCustomers())
.Returns(() =>
{
// Parse the filter and apply it to the customer list
var odataQuery = new ODataQueryOptions<Customer>(
new ODataQueryContext(model, typeof(Customer)),
request
);
var filteredCustomers = odataQuery.ApplyTo(customers.AsQueryable());
return filteredCustomers as IQueryable<Customer>;
});
// ... (existing code)
}
这里我删除了一个条件来检查是否应用了过滤器。