Unit testing 在一个干净的体系结构中测试做不止一件事的Interactor方法
我一直在阅读有关单元测试的书籍&并试图实现涉及这两个方面的东西 据我所知,一个干净的体系结构是结构化的,以便可以对Interactor对象的方法进行单元测试 但是,当用例类似于“创建一个文件,其中的内容是以某种格式从某些数据中计算出来的”时,我会感到困惑,因为它不是单一的(有文件内容的计算和文件的创建,这两者都在用例中) 下面是一些说明我的情况的伪代码:Unit testing 在一个干净的体系结构中测试做不止一件事的Interactor方法,unit-testing,clean-architecture,Unit Testing,Clean Architecture,我一直在阅读有关单元测试的书籍&并试图实现涉及这两个方面的东西 据我所知,一个干净的体系结构是结构化的,以便可以对Interactor对象的方法进行单元测试 但是,当用例类似于“创建一个文件,其中的内容是以某种格式从某些数据中计算出来的”时,我会感到困惑,因为它不是单一的(有文件内容的计算和文件的创建,这两者都在用例中) 下面是一些说明我的情况的伪代码: /* We are in an Interactor (i.e. UseCaseObject) * This method 1)comput
/* We are in an Interactor (i.e. UseCaseObject)
* This method 1)computes fileContent and 2)writes it into a file.
*/
public void CreateFileFromData(someDataInSomeFormat) {
var parsedData = SomeParser.Parse(someDataInSomeFormat);
string fileContent = ???;
WriteFile(fileContent);
}
我的问题如下:
您不知道用于计算的数据将从何处“加载”,但例如,让我们假设数据将从另一个文件读取 您的交互者将有三个依赖项
-读取文件
-计算新文件的数据
-写入文件
public class Interactor
{
public Interactor(IReader reader, ICalculator calculator, IWriter writer)
{ }
public void DoJob()
{
var data = reader.Read();
var calculatedData = calculator.Calculate(data);
writer.Write(calculatedData);
}
}
通过这种方法,交互者将负责“组合”完成任务所需的步骤
您可以通过模拟所有依赖项来简单地测试Interactor
其中:
IReader
和IWriter
是网关
ICalculator
是interactior使用的用例的实现细节
Interactor中定义的方法必须是统一的吗?(例如,只做
(一件事)
方法应该做一件事——执行与用例相关的任务。如果任务需要使用网关(外部资源),或者任务很复杂,无法将其保存在一个方法中,那么您将引入所有必需的单元作为依赖项,交互者的责任是将它们“粘合”在一起
Interactor中定义的方法必须经过单元测试吗?(我看到一个
函数,无论是否为单一的,作为可测试单元,如果
这是不正确的)
只抽象网关(外部资源)-然后您可以测试interactor的整个逻辑。如果您先编写测试-您将编写测试,整个逻辑可以在一个函数中(它可能/应该是丑陋的spagetti代码,这会使测试通过)。然后,当您看到整个实现过程时,您可以开始通过将内容移动到专用类来移动员工
哪个类必须以干净的方式保存fileContent的计算
建筑
如果是简单的单行计算,它可以是交互器。但我更喜欢为计算引入专用类,并将其作为依赖项引入。虽然测试将保留在interactor中,专用计算类将通过interactor测试进行测试,但Clean体系结构的一个核心方面是所有应用程序业务逻辑都在interactor方法中。这意味着你也希望你的主要测试集中在交互者身上,通常使用单元测试和低级验收测试
在设计你的交互方法时,你仍然应该遵循SRP:应该只有一个改变的理由。
你也可以结合互动者来遵循SRP
如果文件内容的计算是u的应用程序业务逻辑,那么它应该在Interactor方法中
有关互动者的详细讨论,请查看我的帖子:谢谢你的回答。然而,它没有提到干净的体系结构,我的问题是它所固有的。您提到“数据将‘加载’到哪里”这一事实似乎表明您的答案超出了Clean体系结构的范围,因为后者通过确定的概念(如“实体”和“网关”)来处理这类事情。您能更清楚地说明您的答案如何适合干净的体系结构吗?谢谢!最后一件事:即使你回答了我的第三个问题,你能否在你的回答中澄清全部三个问题的答案,以供未来读者参考?根据我的理解,应该是:[1:No][2:Yes][3:interactior实现接口的实现细节]再次感谢!再想一想,在阅读之后,似乎一个好的单元测试是一个在我改变函数内部时不会中断的测试。据我所知,您的方法将创建一个测试,在我决定更改Interactor函数的内部时,该测试将中断!(参见我的链接中提供的非常类似的示例)@Minh-T–mTRAN-check更新的答案。你只需要抽象(模拟)依赖关系,这会使测试变慢(外部资源)。我在这篇文章中读到的东西帮助我,教会了我很多东西(这导致我花了2天时间阅读各种各样的书籍),事后我发现了问题的答案。当我输入自己的答案时,我意识到它都包含在你的答案中。很抱歉,我的想法花了这么长时间才成熟到可以像现在这样阅读你的答案。我将您的答案标记为答案:)出于建设性的目的,这绝对不是对您答案的反馈,而是对我的问题的反馈,现在我找到了问题的答案(非常感谢您在这里和您的文章中的所有链接),我意识到事实上我只将WriteFile()视为用例的主要和最后一步,这让我重新考虑把计算放在哪里;事实上,情况恰恰相反,写文件代码必须从交互程序移开。显然,你猜不到所有这些,我只是想说,以防它能帮助你在其他帖子中发现真正的问题:)