IRepository и связанные данные? - PullRequest
0 голосов
/ 01 марта 2020

пару недель go я только что прошел тест на собеседование, дело в том, что я решил почти все, кроме одного пункта, который на данный момент, я думаю, невозможно решить. но наверняка я ошибаюсь.

Эта проблема касается связанных данных. Наш серверный API, IRepository, будет возвращать только узел с его непосредственными дочерними элементами (например, представьте, что FakeRepository загружается из базы данных. Вы не должны изменять код в FakeRepository для этого теста).

Представьте, что NodeManager это код на стороне клиента.

Мы хотим убедиться, что на клиенте только один экземпляр указанного c объекта, чтобы наш клиент имел согласованное представление данных в нашем приложении. Тест «LoadingNodeB_ShouldAlwaysReturnTheSameInstance ()» демонстрирует эту проблему. Измените код в NodeManager так, чтобы этот тест прошел.

, поэтому у нас есть IRepo

namespace TestRecruitment.Repository
{
    public interface IRepository
    {
        Node GetNodeAndImmediateChildren(string nodeName);
    }
}  

, и в тестовом проекте у нас есть поддельный репозиторий, который загружает информацию.

using System;

using TestRecruitment.Repository;

namespace TestRecruitment.Test.Repository
{
    public class FakeRepository : IRepository
    {
        /// <summary>
        /// YOU MUST NOT CHANGE THIS METHOD
        /// </summary>
        public Node GetNodeAndImmediateChildren(string nodeName)
        {
            switch (nodeName)
            {
                case "Node A":
                    // do not modify this
                    var nodeB = new Node { Name = "Node B" };
                    var nodeC = new Node { Name = "Node C" };
                    return new Node { Name = "Node A", ImmediateChildren = new[] { nodeB, nodeC } };
                case "Node B":
                    // do not modify this
                    var nodeD = new Node { Name = "Node D" };
                    var nodeE = new Node { Name = "Node E" };
                    return new Node { Name = "Node B", ImmediateChildren = new[] { nodeD, nodeE } };
                case "Node E":
                    var nodeA = new Node { Name = "Node A" };
                    var nodeF = new Node { Name = "Node F" };
                    return new Node { Name = "Node E", ImmediateChildren = new[] { nodeA, nodeF } };
                default:
                    throw new ApplicationException("Unknown node");
            }
        }
    }
}

дело в том, что вы можете изменить только хранилище, вы не можете касаться любого другого кода.

using System.Linq;

namespace TestRecruitment.Repository
{
    public class NodeManager
    {
        private readonly IRepository _nodeRepository;

        public NodeManager(IRepository nodeRepository)
        {
            _nodeRepository = nodeRepository;
        }

        public Node GetNodeAndImmediateChildren(string name)
        {
            return _nodeRepository.GetNodeAndImmediateChildren(name);
        }
    }
}

ну, вот и все.

любой Помощь будет признательна, я просто хочу знать, как ее решить.

Я создал репозиторий github https://github.com/rothariger/TestRecruitment

С уважением!

1 Ответ

1 голос
/ 01 марта 2020

Предполагая, что узел уникально идентифицируется по его имени, один из способов убедиться, что вы возвращаете один и тот же экземпляр, - это сохранить локальный кеш в клиенте и поддерживать коллекцию Node.ImmediateChildren каждый раз, когда вызывается репозиторий:

public class NodeManager
{
    private readonly IRepository _nodeRepository;

    private readonly Dictionary<string, Node> _cachedNodes = new Dictionary<string, Node>();

    public NodeManager(IRepository nodeRepository)
    {
        _nodeRepository = nodeRepository;
    }

    public Node GetNodeAndImmediateChildren(string name)
    {
        var repositoryNode =_nodeRepository.GetNodeAndImmediateChildren(name);
        UpdateCache(repositoryNode);
        return _cachedNodes[repositoryNode.Name];
    }

    private void UpdateCache(Node repositoryNode)
    {
        AddOrUpdateChildrenCollectionInCache(repositoryNode);

        foreach (var childNode in repositoryNode.ImmediateChildren)
        {
            AddOrUpdateChildrenCollectionInCache(childNode);
        }
    }

    private void AddOrUpdateChildrenCollectionInCache(Node repoNode)
    {
        if (_cachedNodes.TryGetValue(repoNode.Name, out var cachedNode))
        {
            cachedNode.ImmediateChildren = repoNode.ImmediateChildren;
        }
        else
        {
            _cachedNodes.Add(repoNode.Name, repoNode);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...