Unit Testing On OData Web API using .net

huangapple go评论96阅读模式
英文:

Unit Testing On OData Web API using .net

问题

我正在尝试在.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)
    {
        _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
{
    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);

        // 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控制器上执行单元测试案例,以筛选数据并返回响应。

英文:

I am trying to implement Unit test cases on .Net OData Web API. However I am facing issue where I am passing a filter in the Http request URL to filter out the data but receiving same sort of mock data which I am sending. Need assistant what and where I am wrong.

Below is my code

here is the customer controller

public class CustomersController : ODataController
    {
        private readonly ICustomerRepository _repository;
        public CustomersController()
        {
            _repository = new CustomerRepository(new ODataSampleEntities());
        }

        public CustomersController(ICustomerRepository repository)
        {
            // this.genericRepository = repository;//new Repository&lt;Customer&gt;();
            _repository = repository;
        }
    
        [EnableQuery]
        public IQueryable&lt;Customer&gt; Get()
        {
            return _repository.GetAllCustomers();
        }
       
    }

Customer Model

public partial class Customer
{
        public int Id { get; set; }
        public string Name { get; set; }
        public string Country { get; set; }
        public string Address { get; set; }
}

Repository

    public interface ICustomerRepository
    {
        //IEnumerable&lt;Customer&gt; GetAllCustomers();
        IQueryable&lt;Customer&gt; GetAllCustomers();
    }

public class CustomerRepository: ICustomerRepository
    {
        private readonly ODataSampleEntities _context;

        public CustomerRepository(ODataSampleEntities context)
        {
            _context = context;
        }

        public virtual IQueryable&lt;Customer&gt; GetAllCustomers()
        {
            return _context.Customers;
        }
    }

Below is the Unit Test case code

public class CustomerControllerTests
    {
        [TestMethod]
        public void GetAllCustomers_ShouldReturnAllCustomers()
        {
            // Arrange
            var customers = new List&lt;Customer&gt;
            {
                new Customer { Id = 1, Name = &quot;John&quot;, Country = &quot;USA&quot;, Address = &quot;USA&quot; },
                new Customer { Id = 2, Name = &quot;Sandesh&quot;, Country = &quot;India&quot;, Address = &quot;Goa India&quot; }
            };
            var request = new HttpRequestMessage(HttpMethod.Get, &quot;https://localhost:44395/Customers?$filter=Name eq &#39;Sandesh&#39; &amp; $top=1&quot;);

            HttpRouteCollection routes = new HttpRouteCollection();
            HttpConfiguration config = new HttpConfiguration(routes) { IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always };
            var Customerbuilder = new ODataConventionModelBuilder();
            Customerbuilder.EntitySet&lt;Customer&gt;(&quot;Customer&quot;);
            var model = Customerbuilder.GetEdmModel();



            // attempting to register at least some non-OData HTTP route doesn&#39;t seem to help
            routes.MapHttpRoute(&quot;Default&quot;, &quot;{controller}/{action}&quot;);
            config.MapODataServiceRoute(&quot;odata&quot;, &quot;odata&quot;, 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(&quot;Customer&quot;))
                )
            );

            var mockRepository = new Mock&lt;ICustomerRepository&gt;();
            mockRepository.Setup(r =&gt; r.GetAllCustomers()).Returns(customers.AsQueryable());
            mockRepository.SetReturnsDefault&lt;IEnumerable&lt;Customer&gt;&gt;(customers.AsQueryable());

            // Create the controller
            var controller = new CustomersController(mockRepository.Object);
            controller.Request = request;

            var options = new ODataQueryOptions&lt;Customer&gt;(context, request);
            //var response = controller.Get(); //as ViewResult;

            // Act
            var result = controller.Get();

            // Assert
            Assert.IsNotNull(result);

             Assert.IsInstanceOfType(result, typeof(IEnumerable&lt;Customer&gt;));

            var contentResult = result;
            Assert.IsNotNull(contentResult);
            Assert.AreEqual(1, contentResult.Count());
            Assert.AreEqual(&quot;Sandesh&quot;, contentResult.First().Name);
        }
    }

Every time I run the unit test it gives me the same mock data even I pass a filter query via request Url. Please assist me to achieve and perform unit test case on my OData web api controller which will filter the data and will give it back response.

答案1

得分: 0

这里我稍微修改了@Saeed Gholamzadeh建议的答案,然后它就可以工作了。我删除了一个条件,用来检查是否应用了筛选器。

英文:

Slightly I modified the @Saeed Gholamzadeh suggested answer and it worked.

[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
    // ... (existing code)

    var customers = new List&lt;Customer&gt;
    {
        new Customer { Id = 1, Name = &quot;John&quot;, Country = &quot;USA&quot;, Address = &quot;USA&quot; },
        new Customer { Id = 2, Name = &quot;Sandesh&quot;, Country = &quot;India&quot;, Address = &quot;Goa India&quot; }
    };

    // Modify the mock repository setup to consider the filter parameter
    mockRepository.Setup(r =&gt; r.GetAllCustomers())
                  .Returns(() =&gt; 
                  {
                          // Parse the filter and apply it to the customer list
                          var odataQuery = new ODataQueryOptions&lt;Customer&gt;(
                              new ODataQueryContext(model, typeof(Customer)), 
                              request
                          );
                          var filteredCustomers = odataQuery.ApplyTo(customers.AsQueryable());
                          return filteredCustomers as IQueryable&lt;Customer&gt;;
                  });

    // ... (existing code)
}

Here I removed a condition to check whether a filter is applied.

答案2

得分: -1

在你的单元测试代码中,你设置了模拟仓库,始终返回相同的一组客户数据,无论请求URL中应用了什么过滤条件。这就是为什么每次运行单元测试时都会获得相同的模拟数据的原因。

为了在单元测试中模拟过滤行为,你需要修改模拟仓库的设置,考虑请求URL中提供的过滤参数,并相应地返回过滤后的数据。

以下是如何实现这一点的步骤:

修改你的单元测试方法,包括在请求URL中添加过滤参数:

[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
    // ...(现有代码)

    // 修改请求URL以包含过滤参数
    var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44395/Customers?$filter=Name eq 'Sandesh'&$top=1");

    // ...(现有代码)
}

更新模拟仓库的设置,以返回经过过滤的数据:

[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
    // ...(现有代码)

    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" }
    };

    // 修改模拟仓库的设置,考虑过滤参数
    mockRepository.Setup(r => r.GetAllCustomers())
                  .Returns((string filter) => 
                  {
                      // 根据过滤参数进行过滤
                      if (string.IsNullOrEmpty(filter))
                      {
                          return customers.AsQueryable(); // 如果没有过滤条件,则返回所有客户
                      }
                      else
                      {
                          // 解析过滤条件并将其应用于客户列表
                          var odataQuery = new ODataQueryOptions<Customer>(
                              new ODataQueryContext(model, typeof(Customer)), 
                              request
                          );
                          var filteredCustomers = odataQuery.ApplyTo(customers.AsQueryable());
                          return filteredCustomers as IQueryable<Customer>;
                      }
                  });

    // ...(现有代码)
}

通过这种设置,模拟仓库现在将应用在请求URL中指定的过滤条件到客户列表,并在调用 controller.Get() 时相应地返回经过过滤的数据。这应该使你能够正确测试你的OData Web API控制器的过滤行为。

英文:

In your unit test code, you are setting up the mock repository to always return the same set of customers, regardless of the filter applied in the request URL. This is why you are getting the same mock data every time you run the unit test.

To simulate the filtering behavior in your unit test, you need to modify the mock repository setup to consider the filter parameter provided in the request URL and return the filtered data accordingly.

Here's how you can achieve that:

Modify your unit test method to include the filter parameter in the request URL:

[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
    // ... (existing code)

    // Modify the request URL to include the filter parameter
    var request = new HttpRequestMessage(HttpMethod.Get, &quot;https://localhost:44395/Customers?$filter=Name eq &#39;Sandesh&#39;&amp;$top=1&quot;);

    // ... (existing code)
}

Update the setup of your mock repository to return the filtered data:

[TestMethod]
public void GetAllCustomers_ShouldReturnFilteredCustomers()
{
    // ... (existing code)

    var customers = new List&lt;Customer&gt;
    {
        new Customer { Id = 1, Name = &quot;John&quot;, Country = &quot;USA&quot;, Address = &quot;USA&quot; },
        new Customer { Id = 2, Name = &quot;Sandesh&quot;, Country = &quot;India&quot;, Address = &quot;Goa India&quot; }
    };

    // Modify the mock repository setup to consider the filter parameter
    mockRepository.Setup(r =&gt; r.GetAllCustomers())
                  .Returns((string filter) =&gt; 
                  {
                      // 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&lt;Customer&gt;(
                              new ODataQueryContext(model, typeof(Customer)), 
                              request
                          );
                          var filteredCustomers = odataQuery.ApplyTo(customers.AsQueryable());
                          return filteredCustomers as IQueryable&lt;Customer&gt;;
                      }
                  });

    // ... (existing code)
}

With this setup, the mock repository will now apply the filter specified in the request URL to the list of customers and return the filtered data accordingly when you call controller.Get(). This should enable you to properly test the filtering behavior of your OData Web API controller.

huangapple
  • 本文由 发表于 2023年7月31日 20:03:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803432.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定