Search code examples
c#unit-testingdictionarynunit

How to create a unit test for dictionary C#


I would like to make an rpn calculator and create unit test using nunit for the dictionary to test operations, but i don't know how to make it.

    static Stack<double> stack { get; set; } = new Stack<double>();

    static Dictionary<string, Action> operators = new Dictionary<string, Action>
    {
        ["+"] = () => { stack.Push(stack.Pop() + stack.Pop()); },
        ["-"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() - x); },
        ["*"] = () => { stack.Push(stack.Pop() * stack.Pop()); },
        ["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); stack.Push(stack.Pop() / x); },
        ["clr"] = () => { stack.Clear(); },
        ["!"] = () => { var x = stack.Pop(); stack.Push(x == 0 ? 1 : 0); },
        ["!="] = () => { stack.Push(stack.Pop() == stack.Pop() ? 0 : 1); },
        ["%"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() % x); },
        ["++"] = () => { var x = stack.Pop(); x++; stack.Push(x); },
        ["--"] = () => { var x = stack.Pop(); x--; stack.Push(x); },
}

EDIT: Executing is like

 while (true)
        {
            Display();
            var readLine = Console.ReadLine();               

            var tokens = readLine.Split(" ").Where(t => t != string.Empty).ToArray();
            foreach (var token in tokens)
            {
                try
                {
                    operators[token].Invoke();
                }
                catch(KeyNotFoundException)
                {
                    stack.Push(double.Parse(token));
                }
            }               
        }

Solution

  • I think you should put stack and operators as private fields in some class called for example CalculatingService . after that you should create public method Calculate(...), which will return calculated value:

    public class CalculatingService : ICalculatingService
    {
        private readonly Stack<double> stack { get; set; }
        private readonly Dictionary<string, Func<double>> operators;
    
        public CalculatingService() 
        {
            stack = new Stack<double>();
            InitDictionary();
        }
        
        public double Calculate(string @operator) =>
            operators[@operator].Invoke();
        
        public void ClearData() => stack.Clear();
        
        private void InitDictionary() => operators = new Dictionary<string, Func<double>>
        {
            ["+"] = () => stack.Pop() + stack.Pop(),
            ["-"] = () => { var x = stack.Pop(); return stack.Pop() - x; },
            ["*"] = () => stack.Pop() * stack.Pop(),
            ["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); return stack.Pop() / x; },
            ["!"] = () => { var x = stack.Pop(); return x == 0 ? 1 : 0; },
            ["!="] = () => stack.Pop() == stack.Pop() ? 0 : 1,
            ["%"] = () => { var x = stack.Pop(); return stack.Pop() % x; },
            ["++"] = () => { var x = stack.Pop(); x++; return x; },
            ["--"] = () => { var x = stack.Pop(); x--; return x; } 
        };
    }
    

    now you can create test methods for all methods in CalculatingService. You can test Calculate(...) by writing x test methods for x operators. I dunno, how do u manage stack - you have to write additional public methods in CalculatingService for stack management like I wrote ClearData().