你如何提供深度模拟对象?

时间:2011-09-18 21:29:09

标签: java junit mocking

我认为我不应该理解测试。我写了很多测试并得到了不错的报道,但我不禁觉得它不直观。

让我解释一下:如果我有一个类,我正在测试一个方法,它需要传递一个类型的大对象,具有各种状态。这个对象反过来包含我不知道的其他对象及其状态,如何为此方法创建模拟或存根对象,并为其提供可以使用的数据。看来我必须用各种内部子对象信息创建一个大对象来练习我的方法。 我很困惑!

4 个答案:

答案 0 :(得分:6)

这里的其他答案指向嘲笑框架,如果你还没有使用,你一定要看看(使用Mockito!)。但是,这几乎可以肯定是您测试的一个例子,告诉您您遇到了设计问题。如果你发现自己必须提供各种不相关的信息和模拟对象才能通过测试,那么你就是

  1. 试图一次测试太多碎片,
  2. 编写一个非常难以阅读和理解的测试,因为由于信噪比低而无法确定测试应该关注什么,和/或
  3. 编写一个极其脆弱的测试,它将打破最微小的,无关的变化,导致高昂的维护成本和“只是让测试通过”的心态,而不关心测试应该测试什么。
  4. 这些都是不是为可测试性而设计的系统的症状,几乎普遍等同于不是为了可读性而设计的系统,这意味着它设计得不好。

    如果您关心测试,请接受测试优先思考和TDD。我强烈推荐几本关于这个主题的书:"xUnit Test Patterns",我已阅读,reviewed"Growing Object-Oriented Software, Guided by Tests",我几乎已经读完了。

答案 1 :(得分:3)

你想要的是一个模拟框架。他们中有很多人。请查看MockitoEasyMock

简而言之,您将使用如下代码:

when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());

允许您指定调用特定方法时的行为,而无需模拟整个对象。如果你有一个非常复杂的对象,你在嘲笑,它会有点复杂,但你基本上只是指定了你期望看到的行为。

答案 2 :(得分:0)

处理具有大量状态和依赖对象的对象的一种方法,你不关心它在EasyMock中使用'漂亮的模拟'(我认为Mockito中的默认模式)。这将始终为模拟对象上的任何方法返回“空”值(null,0或空字符串)。

如果依赖对象需要做某事,那么你需要从对象中返回实际或模拟对象。

例如,在EasyMock中,它看起来像:

Mock mock = createNiceMock(MyClass.class);
// override default 'empty' returns for values you care about
// this could return a mock instead
ChildObj c = new ChildObj("state");
expect(mock.getChildObj()).andReturn(c);
// replay, call methods on object under test, verify here

但是,你可能想从更大的图景开始:你为什么要使用嘲笑?有些人更喜欢仅使用真实对象和存根进行测试,而有些人更喜欢使用模拟进行测试谷歌搜索'模拟v。存根'并阅读前3或4的结果将帮助您决定模拟是否适合您。

答案 3 :(得分:0)

由于你没有提到你正在使用的模拟库,我会建议我使用的是什么。

然而,我还没有尝试过这个功能,因为它对我来说闻起来很糟糕。看看它是否真的不可避免:

Mockito中,您在创建模拟时可能会有一个深层存根:Example in official site