如何用共同的逻辑testing2种方法?

假设我有两个公共方法:

func didSelect(data: Data) { // do something self.view.showText(textForData(data)) } func didDismiss(data: Data) { if data.isSomething { self.view.showText(textForData(data)) } ... } private func textForData(data: Data): String { var text: String if data.distance == nil { text = "..." } else if data.distance < 1000 { text = "\(data.distance) m" } else { text = "\(data.distance / 1000) km" } return text } 

两者都依赖于textForData的格式化逻辑。

textForData (有这个最小化的实现)有3种可能的情况。 如果我testing每个可能的情况下,我的公共职能,我将最终有6个testing方法,其中3个也将testing相同的逻辑,已经由其他3testing。

什么是testing这个的正确方法?

诗:我可以写一个单独的testingtextForData和公共方法的testing中,我断言textForData被调用,但似乎打破了我的类的封装,我不想公开testForData 。 我也不想为我的textForData逻辑创build一个单独的类,因为我最终会为这个当前类创build太多的依赖关系,而且除了这个类以外,其他任何地方的逻辑似乎都不适合。

你在这里有几个select。

  1. 不要testingtextForData
  2. 复制在使用它的公共方法的每个testing中的行为
  3. 使textForData公开
  4. textForData一个公共类

点1和2是不可取的。

你对第3点似乎很奇怪,但这样做有好处。 你可以testing一次这个行为,因为你确实在意这样做。 我不知道斯威夫特,但在其他语言,这并不像看起来那么糟糕。 一般的build议是编码和接口,而不是一个实现。 所以这个类的公共接口将会做didDismissdidDismiss 。 你的生产代码将用这个接口来表示,即使textForData是类的公共方法,你也不能直接访问它。

这里的好消息是,你的testing可以写在一个实现(实际上,他们必须),所以在这里你可以访问所有三种方法。 所以你可以testing你的心中的内容。

点4与点3类似,但是作为单独的类存储。 我会select这个给定的,你可以争辩说,我们已经打破了第3点的单一职责原则。要隐藏这个我会做一个嵌套类开始给你说这个代码只在这个例子中使用。 再次,您的testing将使用与上述相同的想法访问此。

你的代码正朝着拥抱合成的方向发展,因此你应该拥有诸如小类,良好的代码等等的好处。

我认为数据的格式化是自己的责任。 所以你应该把它提取到自己的类。

这个类可以单独进行unit testing。

使用这个类的其他类应该通过使用接口而不是直接类来解耦。 应该注入依赖性(例如在constrcutor中)。 你可以编写一个默认的构造函数来创build默认的类来简化生产代码中的东西(可怜的dependency injection)。

然后你可以模拟格式化程序,并隔离地testing其他类,validationtextForData方法是否正确调用。