0

几个星期前我刚刚参加了一次工作面试的测试,问题是我已经解决了几乎所有问题,除了一点,在这一点上,我想这是不可能解决的。但可以肯定的是我错了。

这个问题处理相关数据。我们的服务器 API,IRepository,将只返回一个节点及其直接子节点(例如,假设 FakeRepository 正在从数据库加载。您不得更改 FakeRepository 中的代码以进行此测试)。

想象一下 NodeManager 是客户端代码。

我们希望确保客户端上只有一个特定对象的实例,以便我们的客户端在我们的应用程序中拥有一致的数据视图。测试“LoadingNodeB_ShouldAlwaysReturnTheSameInstance()”演示了这个问题。修改 NodeManager 中的代码,使该测试通过。

所以,我们有这个 IRepo

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

在一个测试项目中,我们有一个加载信息的 fakerepository。

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

问候!

4

1 回答 1

1

假设节点由其名称唯一标识,确保返回相同实例的一种方法是在客户端中保留本地缓存并在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);
        }
    }
}
于 2020-03-01T19:55:47.417 回答