可以为这个表达式计算器类的私有方法编写单元测试吗
本文关键字:有方法 单元测试 计算器 表达式 | 更新日期: 2023-09-27 18:03:22
我有以下代码
public interface IInterpreter
{
decimal Evaluate(string expression);
}
public class Interpreter : IInterpreter
{
public decimal Evaluate(string expression)
{
if (String.IsNullOrWhiteSpace(expression))
throw new ArgumentException("Parameter " + nameof(expression) + " cannot be empty");
var rpnExpression = ConvertToReversePolishNotation(expression);
return EvaluateReversePolishExpression(rpnExpression);
}
...
}
此类将计算"5+5*6"或"(3-5(*(2+2(+5"等表达式
现在我想写单元测试。这里唯一的公共函数是Evaluate
,根据所有建议,只应对该方法进行测试
问题是,我有一种强烈的感觉,ConvertToReversePolishNotation(expression)
和EvaluateReversePolishExpression(rpnExpression)
函数都必须用单元测试来覆盖。。。如果Evaluate
方法的某些单元测试失败,它不会指出错误在哪里(在ConvertToRPNExpression
方法或EvaluateReversePolishExpression
函数中(。
所以问题是-在这种情况下,为私有函数编写单元测试可以吗
否。
将ConvertToReversePolishNotation
方法重构为一个单独的类。它关心的是转换。
口译员关心的是评估。如果"模拟"转换的输出,那么使用公共Evaluate
方法应该很容易进行测试。
我将创建三个类,一个负责验证,一个用于转换,另一个用于评估。
然后使用构造函数依赖项注入与实际实现解耦。无论是手动实例化它,还是委托Container来启动它,都可以在不需要更改解释器的情况下更改行为。
如果您走这条路,您可以很容易地测试依赖项的调用顺序,因此您将测试解释器的行为。类似,验证,转换,评估。
您可以分别测试单个类的每个实现。
您的类也在制动单一责任原则,因为它负责验证和调用外部类执行操作,所以负责描述事件流。
此外,如果您将Conversion和Evaluation的实现类紧密地耦合在一起,那么您就违反了"打开-关闭"原则。
是的,没关系。
您正在对Evaluate
进行单元测试,它将贯穿ConvertToReversePolishNotation
和EvaluateReversePolishExpression
的实际实现。
Aphelion是正确的,你可以根据自己的责任来分离类,但只有对于ConvertToReversePolishNotation
,如果你这样做的话,你甚至不需要为EvaluateReversePolishExpression
创建一个私有方法,因为这已经是它(目前(正在做的了。在调用evaluate之前,调用者应该调用ConvertToReversePolishNotation
的类,并将其作为参数传入。
如果您还担心不进行private
方法的单元测试,那么您可以使用internal
方法。
脱离主题:您还必须记住如何扩展和扩展此功能。如果您的解释器也想返回除decimal
之外的数据类型,会发生什么情况?难道你不想最大化仿制药吗?
public decimal Evaluate(string expression)
{
if (String.IsNullOrWhiteSpace(expression))
throw new ArgumentException("Parameter " + nameof(expression) + " cannot be empty");
return EvaluateReversePolishExpression(expression);
}