Вызов ViewViewComponentResult.ViewData.Model.Count () создает исключение NullReferenceException - PullRequest
0 голосов
/ 17 марта 2019

Я пытаюсь проверить ViewComponent, чтобы увидеть, возвращает ли он правильное количество элементов RSS. ResultList содержит ссылку на данные модели, и с помощью быстрого просмотра я могу видеть содержимое IEnumerable.

Однако при вызове Count, First или даже ToList возникает исключение NullReferenceException! ResultList не является нулевым.

Что происходит за сценой?

var result = await model.InvokeAsync(listLength);
var resultList = (result as ViewViewComponentResult).ViewData.Model as IEnumerable<LatestArticlesViewComponent.RssItem>;
Assert.Equal(listLength, resultList.Count());

RssItem - очень простой класс

public class RssItem
{
    public string Uri { get; set; }
    public string Title { get; set; }
    public string Summary { get; set; }
}

РЕДАКТИРОВАТЬ: вот полный тест

private LatestArticlesConfig _config;
private Mock<ISyndicationFeedService> _rssMock;
private const string _validUri = "valid";
private const string _invalidUri = "invalid";

private LatestArticlesViewComponent SetupModel()
{
    _config = new LatestArticlesConfig();
    _rssMock = new Mock<ISyndicationFeedService>();
    var rssItems = new List<SyndicationItem>();
    for (int i=0; i<10; i++)
    {
        rssItems.Add(new SyndicationItem($"title{i}", new string(i.ToString()[0], 500), new Uri("http://uri.com")));
    }
    _rssMock.Setup(x => x.Load(_validUri)).Returns(new SyndicationFeed(rssItems));
    _rssMock.Setup(x => x.Load(_invalidUri)).Callback(() => throw new XmlException());
    return new LatestArticlesViewComponent(_config, _rssMock.Object);
}

[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(5)]
public async Task InvokeAsync_ListLength_ListWithSpecifiedLength(int listLength)
{
    var model = SetupModel();
    _config.ArticlesRss = _validUri;

    var result = await model.InvokeAsync(listLength);
    var resultList = GetResultModel(result);

    Assert.Equal(listLength, resultList.Count());
}

private IEnumerable<LatestArticlesViewComponent.RssItem> GetResultModel(IViewComponentResult result)
{
    return (result as ViewViewComponentResult).ViewData.Model as IEnumerable<LatestArticlesViewComponent.RssItem>;
}

и ViewComponent, который я тестирую

public class LatestArticlesViewComponent : ViewComponent
{
    private readonly LatestArticlesConfig _config;
    private readonly ISyndicationFeedService _rss;

    public LatestArticlesViewComponent(LatestArticlesConfig config, ISyndicationFeedService rss)
    {
        _rss = rss ?? throw new ArgumentNullException(nameof(rss));
        _config = config ?? throw new ArgumentNullException(nameof(config));
    }

    public async Task<IViewComponentResult> InvokeAsync(int listLength = 4, int maxTextLength = 128)
    {
        if (listLength < 0)
            throw new ArgumentOutOfRangeException(nameof(listLength), "ListLength cannot be negative.");
        if (maxTextLength < 0)
            throw new ArgumentOutOfRangeException(nameof(maxTextLength), "MaxTextLength cannot be negative.");
        // System.Net.ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;

        try
        {
            var feed = await Task.Run(() => _rss.Load(_config.ArticlesRss));
            var items = feed.Items.Take(listLength).ToList().Select(x => new RssItem()
            {
                Uri = x.Links[0].Uri.ToString(),
                Title = x.Title.Text,
                Summary = TrimText(HtmlToPlainText(x.Summary.Text), maxTextLength)
            });
            return View(items);
        }
        catch {
            return Content(string.Empty);
        }
    }

    private string TrimText(string title, int length)
    {
        var result = title;
        if (title.Length > length)
        {
            result = title.Substring(0, length).Trim();
            result += "&hellip;";
        }
        return result;
    }

    private string HtmlToPlainText(string html) => new Regex("<[^>]*>", RegexOptions.Multiline).Replace(html, string.Empty);

    public class RssItem
    {
        public string Uri { get; set; }
        public string Title { get; set; }
        public string Summary { get; set; }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...