Questions tagged «mocking»

模拟和伪造是隔离代码或组件的方法,以确保单元测试仅针对可测试的代码单元运行,而无需实际利用其他组件或应用程序的依赖项。模拟与伪造的不同之处在于,可以检查模拟以断言测试结果。

11
(为什么)单元测试不测试依赖项很重要?
我了解自动测试的价值,并在问题足够明确的地方使用它,以便我可以提出好的测试用例。但是,我注意到,这里和StackOverflow上的某些人只强调测试一个单元,而不是测试其依赖项。在这里我看不到好处。 为避免测试依赖性而进行的模拟/存根增加了测试的复杂性。它在生产代码中增加了人工灵活性/去耦要求,以支持模拟。(我不同意说这会促进良好设计的任何人。写额外的代码,引入诸如依赖注入框架之类的东西,或者以其他方式增加代码库的复杂性以在没有实际用例的情况下使事情变得更灵活/可插拔/可扩展/解耦是过度设计,而不是好的设计。) 其次,测试依赖项意味着使用其他输入的测试关键的底层代码,而不是那些编写测试的人明确想到的输入。通过在高级功能上运行单元测试而不嘲笑它所依赖的低级功能,我发现了低级功能中的许多错误。理想情况下,这些可以通过单元测试中的低级功能找到,但是总是会漏掉一些情况。 另一面是什么?单元测试不要同时测试其依赖关系真的很重要吗?如果是这样,为什么? 编辑:我可以理解模拟外部依赖项(如数据库,网络,Web服务等)的价值。(感谢Anna Lear激励我进行澄清。)我指的是内部依赖项,即其他类,静态函数等。没有任何直接的外部依赖关系。

11
使用模拟对象时,如何检测单元测试的依赖性问题?
您有一个X类,并且编写了一些验证行为X1的单元测试。还有一个类A,它把X作为依赖项。 为A编写单元测试时,您将模拟X。换句话说,在对A进行单元测试时,您将(假设)X的模拟行为设置为X1。时间的流逝,人们确实在使用您的系统,需要改变,X演变:您修改X以显示行为X2。显然,针对X的单元测试将失败,您需要对其进行调整。 但是A呢?修改X的行为后(由于X的模拟),针对A的单元测试不会失败。当使用“真实”(修改的)X运行时,如何检测A的结果会有所不同? 我期望得到以下答案:“这不是单元测试的目的”,但是单元测试有什么价值呢?它真的只是告诉您,当所有测试通过时,您还没有进行重大更改吗?当某个班级的行为发生变化时(有意或无意),您如何发现(最好以自动化方式)所有后果?我们不应该更多地关注集成测试吗?

11
静态测试对于单元测试而言是否普遍“邪恶”?如果是的话,为什么瑞沙珀推荐它?[关闭]
我发现只有三种方法可以对C#.NET中静态的单元测试(模拟/存根)依赖性进行测试: 鼠 TypeMock JustMock 鉴于其中有两个不是免费的,而另一个没有发布1.0版,因此模拟静态内容并不是一件容易的事。 这是否构成静态方法和此类“邪恶”(就单元测试而言)?如果是这样,为什么harsharper希望我做任何可以静态的事情?(假设重新剃刀也不是“邪恶的”。) 澄清: 我是在谈论要对方法进行单元测试并且该方法在其他单元/类中调用静态方法的情况。根据单元测试的大多数定义,如果仅让被测方法在另一个单元/类中调用静态方法,则您不是单元测试,而是集成测试。(有用,但不是单元测试。)

8
在不进行广泛模拟的情况下,应该如何编写单元测试?
据我了解,单元测试的重点是隔离测试代码单元。这意味着: 它们不应被代码库中其他地方不相关的代码更改破坏。 与集成测试相反(集成测试可能会中断),只有一个单元测试应该通过被测试单元中的错误来破坏。 所有这些暗示着,应该模拟掉测试单元的所有外部依赖关系。我的意思是所有外部依赖关系,而不仅仅是网络,文件系统,数据库等“外部层”。 这得出一个合理的结论,几乎每个单元测试都需要模拟。另一方面,谷歌对嘲笑的快速搜索显示了成千上万的文章声称“嘲笑是一种代码味道”,应该(尽管不完全)避免。 现在,到问题。 单元测试应如何正确编写? 它们和集成测试之间的界线到底在哪里? 更新1 请考虑以下伪代码: class Person { constructor(calculator) {} calculate(a, b) { const sum = this.calculator.add(a, b); // do some other stuff with the `sum` } } 可以在Person.calculate不模拟Calculator依赖关系的情况下测试该方法的测试(假定,它Calculator是不访问“外部世界”的轻量级类)可以视为单元测试吗?

3
这是Mockito的reset方法的适当用法吗?
我的测试类中有一个私有方法,该方法构造一个常用Bar对象。Bar构造函数someMethod()在我的模拟对象中调用方法: private @Mock Foo mockedObject; // My mocked object ... private Bar getBar() { Bar result = new Bar(mockedObject); // this calls mockedObject.someMethod() } 在我的某些测试方法中someMethod,该特定测试也调用了我要检查的方法。类似于以下内容: @Test public void someTest() { Bar bar = getBar(); // do some things verify(mockedObject).someMethod(); // <--- will fail } 这将失败,因为模拟对象已someMethod被调用两次。我不想让我的测试方法关心方法的副作用getBar(),所以在末尾重置模拟对象是否合理getBar()? private Bar getBar() { Bar …
68 java  mocking 

6
如何测试难以模拟对象的系统?
我正在使用以下系统: Network Data Feed -> Third Party Nio Library -> My Objects via adapter pattern 最近,我们遇到了一个问题,即我更新了所使用的库的版本,这尤其导致时间戳(第三方库返回该时间戳long)从时期后的毫秒数更改为时期后的毫微秒。 问题: 如果编写模拟第三方库对象的测试,则如果我对第三方库的对象犯了错误,则我的测试将是错误的。例如,我没有意识到时间戳会改变精度,这导致需要更改单元测试,因为我的模拟返回了错误的数据。这不是库中的错误,它的发生是因为我错过了文档中的某些内容。 问题是,我无法确定这些数据结构中包含的数据,因为如果没有真实的数据馈送,我将无法生成真实的数据。这些对象又大又复杂,并且其中包含许多不同的数据。第三方库的文档很差。 问题: 如何设置测试以测试此行为?我不确定我可以在单元测试中解决此问题,因为测试本身很容易出错。另外,集成系统又大又复杂,容易遗漏一些东西。例如,在上述情况下,我已经在几个地方正确地调整了时间戳记处理,但是我错过了其中之一。在我的集成测试中,该系统似乎在做正确的事情,但是当我将其部署到生产环境(具有大量数据)时,问题变得很明显。 我目前没有集成测试过程。测试本质上是:尝试保持单元测试良好,在出现问题时添加更多测试,然后部署到我的测试服务器并确保一切正常,然后部署到生产中。这个时间戳问题通过了单元测试,因为模拟创建错误,然后通过了集成测试,因为它没有引起任何直接的,明显的问题。我没有质量检查部门。

2
集成测试是否使用模拟?
我目前在软件测试课程中,对于我们的学期项目,我们必须对其执行多种类型的测试,例如单元测试和集成测试。教授说,对于集成测试,在我们的集成测试中使用了模拟和模拟库(例如EasyMock和Mockito)。不过我有点困惑。集成测试是在类,模块,服务等外部进行测试。如果要测试多个类和服务,为什么在集成测试中应适当使用模拟和存根?

3
假冒被测课程的一部分可以吗?
假设我有一个类(请原谅人为的示例及其错误的设计): class MyProfit { public decimal GetNewYorkRevenue(); public decimal GetNewYorkExpenses(); public decimal GetNewYorkProfit(); public decimal GetMiamiRevenue(); public decimal GetMiamiExpenses(); public decimal GetMiamiProfit(); public bool BothCitiesProfitable(); } (请注意,GetxxxRevenue()和GetxxxExpenses()方法具有依赖项,这些依赖项已被删除) 现在,我正在对取决于GetNewYorkProfit()和GetMiamiProfit()的BothCitiesProfitable()进行单元测试。可以对GetNewYorkProfit()和GetMiamiProfit()存根吗? 似乎如果我不这样做,那么我同时要同时测试GetNewYorkProfit()和GetMiamiProfit()以及BothCitiesProfitable()。我必须确保为GetxxxRevenue()和GetxxxExpenses()设置存根,以便GetxxxProfit()方法返回正确的值。 到目前为止,我只看到了对外部类而非内部方法的依赖关系进行存根的示例。 如果可以的话,是否应该使用一种特定的模式来执行此操作? 更新 我担心我们可能会遗漏核心问题,这可能是我的拙劣例子的错。基本的问题是:如果一个类中的方法依赖于该类中另一个公开的方法,是否可以(甚至建议)将另一个方法存根? 也许我错过了一些东西,但是我不确定分班总是有意义的。也许另一个更好的例子是: class Person { public string FirstName() public string LastName() public string FullName() } 全名定义为: public string …

3
由于需要过多的模拟而导致单元测试脆弱
关于我们在团队中实施的单元测试,我一直在遇到越来越烦人的问题。我们正在尝试将单元测试添加到设计不良的旧代码中,尽管我们在实际添加测试方面没有遇到任何困难,但是我们开始为测试的结果而苦恼。 作为问题的一个示例,假设您有一个方法在执行过程中调用了5个其他方法。此方法的测试可能是确认是否由于调用这5个其他方法之一而导致了行为。因此,由于单元测试应该仅出于一个原因和一个原因而失败,因此您希望消除调用这四种方法并对其进行模拟而导致的潜在问题。大!执行单元测试,忽略模拟的方法(它们的行为可以作为其他单元测试的一部分进行确认),并且验证有效。 但是存在一个新问题-单元测试对您如何确认将来行为和任何其他4种方法的签名变化或需要添加到“父方法”的任何新方法有深入了解。导致必须更改单元测试以避免可能的故障。 自然地,可以通过简单地使更多的方法完成更少的行为而在某种程度上缓解该问题,但是我希望可以找到一个更优雅的解决方案。 这是捕获问题的示例单元测试。 简要说明一下,“ MergeTests”是一个单元测试类,它继承自我们正在测试的类,并根据需要覆盖行为。这是我们在测试中采用的“模式”,允许我们覆盖对外部类/依赖项的调用。 [TestMethod] public void VerifyMergeStopsSpinner() { var mockViewModel = new Mock<MergeTests> { CallBase = true }; var mockMergeInfo = new MergeInfo(Mock.Of<IClaim>(), Mock.Of<IClaim>(), It.IsAny<bool>()); mockViewModel.Setup(m => m.ClaimView).Returns(Mock.Of<IClaimView>); mockViewModel.Setup( m => m.TryMergeClaims(It.IsAny<Func<bool>>(), It.IsAny<IClaim>(), It.IsAny<IClaim>(), It.IsAny<bool>(), It.IsAny<bool>())); mockViewModel.Setup(m => m.GetSourceClaimAndTargetClaimByMergeState(It.IsAny<MergeState>())).Returns(mockMergeInfo); mockViewModel.Setup(m => m.SwitchToOverviewTab()); mockViewModel.Setup(m => m.IncrementSaveRequiredNotification()); mockViewModel.Setup(m …

6
从TDD的角度来看,如果我针对实时端点而不是模拟进行测试,那我是一个坏人吗?
我虔诚地遵循TDD。我的项目通常具有有意义的测试用例,测试覆盖率可达85%或更高。 我使用HBase进行了大量工作,而主要的客户端接口HTable实在令人难以接受。与编写使用实时端点的测试相比,编写我的单元测试要花3到4倍的时间。 从哲学上讲,我知道使用模拟的测试应优先于使用实时端点的测试。但是模拟HTable是一个严重的难题,我不确定它相对于针对实时HBase实例进行测试是否具有很多优势。 我们团队中的每个人都在其工作站上运行一个单节点HBase实例,而我们的Jenkins机器上运行着一个单节点HBase实例,因此这不是可用性问题。实时端点测试显然比使用模拟的测试花费更长的时间,但是我们并不在乎。 现在,我为我的所有类编写了实时端点测试和基于模拟的测试。我很想抛弃模拟游戏,但我不希望结果因此而下降。 你们怎么想

3
模拟在生产代码中引入处理
假设有一个IReader接口,一个IReader接口ReaderImplementation的实现以及一个使用和处理来自读取器的数据的类ReaderConsumer。 public interface IReader { object Read() } 实作 public class ReaderImplementation { ... public object Read() { ... } } 消费者: public class ReaderConsumer() { public string location // constructor public ReaderConsumer() { ... } // read some data public object ReadData() { IReader reader = new ReaderImplementation(this.location) data …

3
选择模拟框架的关键因素是什么?
我希望开始使用单元测试中的对象。似乎那里有很多好的模拟框架。 不同的框架有不同的目标受众吗? 在选择适合自己情况的框架时应考虑哪些因素?
15 mocking 


7
如何避免需要对私有方法进行单元测试
我知道您不应该测试私有方法,并且如果您看起来需要测试私有方法,那么那里可能会有一个类在等待发布。 但是,我不想拥有大量的类来测试它们的公共接口,我发现对于许多类来说,如果仅测试公共方法,最终我就不得不模拟很多依赖,而单元测试就是巨大且难以遵循。 我更喜欢在测试公共方法时嘲笑私有方法,而在测试私有方法时嘲笑外部依赖关系。 我疯了吗?

1
单元测试API客户端和包装器
我一直在兜圈子,试图找出对我正在开发的API客户端库进行单元测试的最佳方法。该库具有一个Client基本上与API进行1:1映射的Wrapper类,以及一个额外的类,该类在的顶部提供了更加用户友好的界面Client。 Wrapper --> Client --> External API 我首先针对Client和编写了一系列测试Wrapper,实际上只是测试它们是否转发到操作的任何适当功能(Wrapper在上操作Client,并Client在HTTP连接上操作)。但是,我开始对此感到不舒服,因为我感觉自己正在测试这些类的实现,而不是接口。从理论上讲,我可以将这些类更改为具有另一个完全有效的实现,但是我的测试将失败,因为未调用我希望调用的函数。对我来说,这听起来像是脆弱的考验。 之后,我考虑了类的接口。测试应该验证类是否确实完成了其应做的工作,而不是他们是如何完成的。那我该怎么做呢?首先想到的是对外部API请求进行存根。但是,我担心过度简化外部服务。我见过的很多存根API的示例都给出了罐头响应,这听起来像是一种非常简单的方法,可以仅测试您的代码是否针对假API正确运行。另一种方法是模拟服务,这是不可行的,并且每当真实服务发生变化时就需要保持最新状态-感觉像是过分杀伤和浪费时间。 最后,我从程序员SE的另一个答案中读取了此内容: 远程API客户端的工作是发出某些调用-不多也不少。因此,它的测试应验证它是否发出了这些呼叫-不多也不少。 现在,我或多或少地确信-测试时Client,我需要测试的是它向API发出了正确的请求(当然,总有API会更改但我的测试继续通过的可能性-但这就是集成测试很有用的地方)。由于Client与API只是1:1的映射,因此在将一个有效实现更改为另一个之前,我的担心并没有真正适用-的每种方法只有一个有效实现Client。 但是,我仍然坚持Wrapper上课。我看到以下选项: 我对Client类进行存根处理,然后测试是否调用了适当的方法。这样,我做的与上述相同,但是将其Client作为API的替代。这使我回到了起点。再一次,这给了我测试实现而不是界面的不舒服的感觉。将Wrapper很可能使用了完全不同的客户端实现。 我创建一个模拟Client。现在,我必须决定对它进行模拟的程度-创建服务的完整模拟将花费很多精力(比库本身要付出更多的工作)。API本身很简单,但是服务却很复杂(本质上是一个对数据进行操作的数据存储)。再说一次,我将必须使模拟与real保持同步Client。 我只是测试是否正在发出适当的HTTP请求。这意味着Wrapper将通过一个真实的Client对象进行调用以发出这些HTTP请求,因此我并不是在单独测试它。这使得它有点可怕的单元测试。 因此,我对这些解决方案都不满意。你会怎么做?有正确的方法去做吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.