C# 为这个表达式计算器类的私有方法编写单元测试可以吗?
C# 为这个表达式计算器类的私有方法编写单元测试可以吗?,c#,unit-testing,expression,C#,Unit Testing,Expression,我有以下代码 public interface IInterpreter { decimal Evaluate(string expression); } public class Interpreter : IInterpreter { public decimal Evaluate(string expression) { if (String.IsNullOrWhiteSpace(expression)) throw new
我有以下代码
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”等表达式现在我想写单元测试。这里唯一的公共功能是
评估
,根据所有建议,只有该方法应进行测试问题是我强烈地感觉到,
ConvertToReversePolishNotation(expression)
EvaluateReversePolishExpression(rpnExpression)
函数都必须包含在单元测试中。。。如果某个单元测试因Evaluate
方法而失败,它将不会指出错误的位置(在convertorpnexpression
方法或EvaluateReversePolishExpression
函数中)。
所以问题是-在这种情况下为私有函数编写单元测试可以吗?否 将
ConvertToReversePolishNotation
方法重构为一个单独的类。它关注的是转换
口译员关心的是评估。如果您“模拟”转换的输出,那么使用public
Evaluate
方法应该很容易进行测试。是的,可以。
您正在进行单元测试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);
}
我将创建三个类,一个负责验证,一个负责转换,一个负责评估 而不是使用构造函数依赖项注入来与实际实现解耦。 您可以手动实例化它,也可以委托容器来初始化它,这样您就可以在不改变解释器的情况下更改行为 如果沿着这条路线走下去,您可以很容易地测试依赖项的调用顺序,因此您将测试解释器的行为。 比如,验证、转换、评估 您可以单独测试单个类的每个实现 您的类也遵循单一责任原则,因为它负责验证并调用外部类来执行操作,所以它负责描述事件流
此外,如果您将实现类紧密地结合起来进行转换和评估,那么您就违反了开-关原则。@您可以使用“单一责任原则”来验证类是否过于复杂。通常,单元测试问题是一个很好的指标,验证只是一个简单的保护。为什么要将input guard移动到一个单独的类?据我所知,你同意@Aphelion,但你的简短回答是肯定的,而他的答案是否定的:)@我很失望,我同意你可以将它分开,我不同意他的
No
不为私有函数编写单元测试是不好的。这基本上是你大胆的问题。有时候,忽视是不可避免的。仅仅因为其中一本书/作者说为私有函数编写单元测试不好并不意味着这是一条硬规则。好吧,他的问题是在这种情况下的,而不是一条硬规则:)