C# 模拟服务未返回正确的值。

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

C# Mocked service does not return correct values

问题

I've translated the code portion you provided into English:

I have an ASP.NET Core 6 web app where I display news. It has a `Bulgaria` action method that returns up to 30 news on a page.
Using Selenium and Moq, I am trying to write a test to check if the result is not null and if it displays 30 news.

Initially, the test passed and everything seemed fine. However, I noticed that the 30 news were actually from the real database instead of the fake ones I had prepared. Subsequently, I changed the fake news to 20 and modified the test to verify if there were 20 news, but it started to fail because it still returned 30 from the real database.

I have been working on this for about a day and a half now. Since I don't have much experience in testing, especially with Selenium and Moq, I haven't been able to figure out the problem yet.

Here is my `ControllerTest.cs`:

[Fact]
public void BulgariaDisplaysThirtyNewsAndIsNotNull()
{
    // Arrange
    var mockNewsService = new Mock<INewsService>();

    // Create 20 fake news items
    var fakeNewsItems = new List<NewsModel>();
    for (int i = 0; i < 20; i++)
    {
        var fakeNewsItem = new NewsModel
        {
            Id = i + 1,
            Title = $"Fake News {i + 1}",
            Content = $"This is fake news {i + 1}"
        };

        fakeNewsItems.Add(fakeNewsItem);
    }

    var pageNumber = 1;
    var numberOfNewsOnPage = 10;
    var allNews = 20;
    var totalPages = 2;

    mockNewsService.Setup(service => service.RetrieveAllNewsCountAsync())
        .ReturnsAsync(allNews);
    mockNewsService.Setup(service => service.RetrieveAllNewsForThePageAsync(pageNumber, numberOfNewsOnPage))
        .ReturnsAsync(fakeNewsItems);

    var newsController = new NewsController(mockNewsService.Object, null);

    // Act
    var result = newsController.Bulgaria(pageNumber).GetAwaiter().GetResult();

    // Assert
    Assert.NotNull(result);
    Assert.IsType<ViewResult>(result);

    var viewResult = (ViewResult)result;
    Assert.IsType<DisplayListOfNewsViewModel>(viewResult.Model);

    var viewModel = (DisplayListOfNewsViewModel)viewResult.Model;
    Assert.Equal(fakeNewsItems, viewModel.News);
    Assert.Equal(20, viewModel.News.Count);
}

Here is my Bulgaria action method and the NewsController it is in:

public class NewsController : Controller
{
    private readonly INewsService news;
    private readonly IUserService users;

    public NewsController(INewsService news, IUserService users)
    {
        this.news = news;
        this.users = users;
    }

    public async Task<IActionResult> Bulgaria(int? pageNumber)
    {
        var numberOfNewsOnPage = ControllerConstants.NumberOfNewsOnAPage;

        if (pageNumber == null)
        {
            pageNumber = 1;
        }

        var allNews = await this.news.RetrieveAllNewsCountAsync();

        if (pageNumber < 1)
        {
            return RedirectToAction("Bulgaria", new { pageNumber = 1 });
        }

        var newsOnThePage = await this.news.RetrieveAllNewsForThePageAsync(pageNumber, numberOfNewsOnPage);
        var totalPages = (int)Math.Ceiling((double)allNews / numberOfNewsOnPage);

        if (pageNumber > totalPages)
        {
            return RedirectToAction("Bulgaria", new { pageNumber = totalPages });
        }

        var viewModel = new DisplayListOfNewsViewModel
        {
            News = newsOnThePage,
            PageNumber = pageNumber.Value,
            NumberOfNewsOnPage = numberOfNewsOnPage,
            TotalNewsCount = allNews,
            TotalPages = totalPages
        };

        return View(viewModel);
    }
}

And here is my NewsService.cs with only the used methods just to be sure:

namespace NewsWebSiteScraper.Services.News
{
    using Microsoft.EntityFrameworkCore;
    using NewsWebSiteScraper.Data;
    using NewsWebSiteScraper.Data.Models;
    using NewsWebSiteScraper.Models.News;

    public class NewsService : INewsService
    {
        private readonly NewsWebSiteScraperDbContext data;

        public NewsService(NewsWebSiteScraperDbContext data)
        {
            this.data = data;
        }

        public async Task<List<NewsModel>> RetrieveAllNewsForThePageAsync(int? pageNumber, int numberOfNewsOnPage)
        {
            var allNews = await this.data
                .News
                .OrderByDescending(n => n.Date)
                .Where(n => n.Date != new DateTime(1000, 1, 1, 12, 30, 0))
                .Select(n => new NewsModel
                {
                    Id = n.Id,
                    Title = n.Title,
                    ImageUrl = n.ImageUrl
                })
                .Skip((pageNumber.Value - 1) * numberOfNewsOnPage)
                .Take(numberOfNewsOnPage)
                .ToListAsync();

            return allNews;
        }

        public async Task<int> RetrieveAllNewsCountAsync()
        {
            var totalNewsCount = await this.data
                .News
                .Where(n => n.Date != new DateTime(1000, 1, 1, 12, 30, 0))
                .CountAsync();

            return totalNewsCount;

        }
    }
}

Please note that the code may require further debugging and adjustment based on your specific application and requirements.

英文:

I have an ASP.NET Core 6 web app where I display news. It has a Bulgaria action method that returns up to 30 news on a page.
Using Selenium and Moq, I am trying to write a test to check if the result is not null and if it displays 30 news.

Initially, the test passed and everything seemed fine. However, I noticed that the 30 news were actually from the real database instead of the fake ones I had prepared. Subsequently, I changed the fake news to 20 and modified the test to verify if there were 20 news, but it started to fail because it still returned 30 from the real database.

I have been working on this for about a day and a half now. Since I don't have much experience in testing, especially with Selenium and Moq, I haven't been able to figure out the problem yet.

Here is my ControllerTest.cs:

    [Fact]
    public void BulgariaDisplaysThirtyNewsAndIsNotNull()
    {
        // Arrange
        var mockNewsService = new Mock&lt;INewsService&gt;();

        // Create 20 fake news items
        var fakeNewsItems = new List&lt;NewsModel&gt;();
        for (int i = 0; i &lt; 20; i++)
        {
            var fakeNewsItem = new NewsModel
            {
                Id = i + 1,
                Title = $&quot;Fake News {i + 1}&quot;,
                Content = $&quot;This is fake news {i + 1}&quot;
            };

            fakeNewsItems.Add(fakeNewsItem);
        }

        var pageNumber = 1;
        var numberOfNewsOnPage = 10;
        var allNews = 20;
        var totalPages = 2;

        mockNewsService.Setup(service =&gt; service.RetrieveAllNewsCountAsync())
            .ReturnsAsync(allNews);
        mockNewsService.Setup(service =&gt; service.RetrieveAllNewsForThePageAsync(pageNumber, numberOfNewsOnPage))
            .ReturnsAsync(fakeNewsItems);

        var newsController = new NewsController(mockNewsService.Object, null);

        // Act
        var result = newsController.Bulgaria(pageNumber).GetAwaiter().GetResult();

        // Assert
        Assert.NotNull(result);
        Assert.IsType&lt;ViewResult&gt;(result);

        var viewResult = (ViewResult)result;
        Assert.IsType&lt;DisplayListOfNewsViewModel&gt;(viewResult.Model);

        var viewModel = (DisplayListOfNewsViewModel)viewResult.Model;
        Assert.Equal(fakeNewsItems, viewModel.News);
        Assert.Equal(20, viewModel.News.Count);
    }

Here is my Bulgaria action method and the NewsController it is in:

public class NewsController : Controller
{
    private readonly INewsService news;
    private readonly IUserService users;

    public NewsController(INewsService news, IUserService users)
    {
        this.news = news;
        this.users = users;
    }

    public async Task&lt;IActionResult&gt; Bulgaria(int? pageNumber)
    {
        var numberOfNewsOnPage = ControllerConstants.NumberOfNewsOnAPage;

        if (pageNumber == null)
        {
            pageNumber = 1;
        }

        var allNews = await this.news.RetrieveAllNewsCountAsync();

        if (pageNumber &lt; 1)
        {
            return RedirectToAction(&quot;Bulgaria&quot;, new { pageNumber = 1 });
        }

        var newsOnThePage = await this.news.RetrieveAllNewsForThePageAsync(pageNumber, numberOfNewsOnPage);
        var totalPages = (int)Math.Ceiling((double)allNews / numberOfNewsOnPage);

        if (pageNumber &gt; totalPages)
        {
            return RedirectToAction(&quot;Bulgaria&quot;, new { pageNumber = totalPages });
        }

        var viewModel = new DisplayListOfNewsViewModel
        {
            News = newsOnThePage,
            PageNumber = pageNumber.Value,
            NumberOfNewsOnPage = numberOfNewsOnPage,
            TotalNewsCount = allNews,
            TotalPages = totalPages
        };

        return View(viewModel);
    }
}

And here is my NewsService.cs with only the used methods just to be sure:

namespace NewsWebSiteScraper.Services.News
{
    using Microsoft.EntityFrameworkCore;
    using NewsWebSiteScraper.Data;
    using NewsWebSiteScraper.Data.Models;
    using NewsWebSiteScraper.Models.News;

    public class NewsService : INewsService
    {
        private readonly NewsWebSiteScraperDbContext data;

        public NewsService(NewsWebSiteScraperDbContext data)
        {
            this.data = data;
        }

        public async Task&lt;List&lt;NewsModel&gt;&gt; RetrieveAllNewsForThePageAsync(int? pageNumber, int numberOfNewsOnPage)
        {
            var allNews = await this.data
                .News
                .OrderByDescending(n =&gt; n.Date)
                .Where(n =&gt; n.Date != new DateTime(1000, 1, 1, 12, 30, 0))
                .Select(n =&gt; new NewsModel
                {
                    Id = n.Id,
                    Title = n.Title,
                    ImageUrl = n.ImageUrl
                })
                .Skip((pageNumber.Value - 1) * numberOfNewsOnPage)
                .Take(numberOfNewsOnPage)
                .ToListAsync();

            return allNews;
        }

        public async Task&lt;int&gt; RetrieveAllNewsCountAsync()
        {
            var totalNewsCount = await this.data
                .News
                .Where(n =&gt; n.Date != new DateTime(1000, 1, 1, 12, 30, 0))
                .CountAsync();

            return totalNewsCount;

        }
    }
}

答案1

得分: 0

原来整个问题出在 Bulgaria 操作方法中。在第一行 - var numberOfNewsOnPage = ControllerConstants.NumberOfNewsOnAPage; 它设置了 numberOfNewsOnPage 变量,后来在服务方法中使用。在测试中,如果我没有提供正确的值,它就无法匹配服务方法,问题就出现了。

英文:

Turns out that the whole problem was in the Bulgaria action method. At the first line - var numberOfNewsOnPage = ControllerConstants.NumberOfNewsOnAPage; it sets the numberOfNewsOnPage variable that are later used in the service method. And in the test if I don't give the correct value it does not match the service method and the problem occurs.

huangapple
  • 本文由 发表于 2023年5月22日 03:09:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76301500.html
匿名

发表评论

匿名网友

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

确定