我正在努力学习如何编写测试。我也在学习Java,有人告诉我应该学习/使用/练习jMock,我在网上发现了一些有助于某些扩展的文章:
http://www.theserverside.com/news/1365050/Using-JMock-in-Test-Driven-Development
http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock
我发现的大多数文章都是关于测试驱动的开发,首先编写测试然后编写代码以使测试通过。我现在不是在寻找,我正在尝试使用jMock为现有代码编写测试。
official documentation对我来说至少是晦涩难懂的。有没有人有更好的方法来学习这个。好书/链接/教程对我很有帮助。谢谢
编辑 - 更具体的问题:
http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock - 来自这篇文章
试图模仿这个简单的类:
import java.util.Map;
public class Cache {
private Map<Integer, String> underlyingStorage;
public Cache(Map<Integer, String> underlyingStorage) {
this.underlyingStorage = underlyingStorage;
}
public String get(int key) {
return underlyingStorage.get(key);
}
public void add(int key, String value) {
underlyingStorage.put(key, value);
}
public void remove(int key) {
underlyingStorage.remove(key);
}
public int size() {
return underlyingStorage.size();
}
public void clear() {
underlyingStorage.clear();
}
}
以下是我尝试创建测试/模拟的方法:
public class CacheTest extends TestCase {
private Mockery context;
private Map mockMap;
private Cache cache;
@Override
@Before
public void setUp() {
context = new Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
mockMap = context.mock(Map.class);
cache = new Cache(mockMap);
}
public void testCache() {
context.checking(new Expectations() {{
atLeast(1).of(mockMap).size();
will(returnValue(int.class));
}});
}
}
它通过了测试,基本上没有做任何事情,我想要的是创建一个地图并检查它的大小,你知道工作的一些变化尝试抓住这个。通过实例了解更好,我在这里测试的其他内容或任何其他练习对我有很大的帮助。 TNX
答案 0 :(得分:5)
这是一个关于使用JUnit和EasyMock的教程(我个人觉得比JMock更容易使用的模拟库):http://www.michaelminella.com/testing/unit-testing-with-junit-and-easymock.html
即使您100%致力于使用JMock,两者之间的概念也是相同的,这可以帮助您更好地理解它们。
模拟的目的是当您测试类A
时,它取决于B
和C
,您对A
的测试使用B
的模拟版本}和C
能够指定其确切的行为,而不是在B
的测试中使用C
和A
的实际实现。否则,您不仅仅测试A
的单个单元,而是隐式测试B
和C
。
答案 1 :(得分:4)
作为JMock的作者,在你对TDD有一些经验之前,我不会从这个技术开始。从基础开始,让它工作。一旦你开始遇到规模和设计方面的困难,请回到这个技术。
Dave Astels的书仍然是一本很好的介绍,我认为这是唯一一本能够很好地解释嘲讽的书。在那之后,你可能(咳咳)考虑我们的“成长面向对象软件,以测试为导向”
对任何告诉你完全针对文件系统进行测试的人进行折扣更快。
答案 2 :(得分:2)
你不需要真正模拟测试这个类,因为它唯一的协作者是一个你可能只是按原样使用的Map。此外,你的班级并没有真正做任何事情(委托除外),这就是为什么你觉得你没有做太多测试。
直接测试可能是(我假设您正在使用JUnit 4 - 您的代码是JUnit 3和4的奇怪混合
@Test
public void sizeIs0WhenEmpty()
{
Map<Integer, String> map = Collections.emptyMap();
Cache cache = new Cache(map)
assertEquals(0, cache.size());
}
使用模拟(假设模拟代码是正确的 - 我不使用JMock)
@Test
public void sizeIs0WhenEmpty()
{
context.checking(new Expectations() {{
atLeast(1).of(mockMap).size();
will(returnValue(0));
}});
assertEquals(0, cache.size());
}
在这两种情况下,您都可以通过将地图设置为要测试的属性来设置系统,然后检查缓存是否具有相同的属性(因为它是直接委托)。
我建议您在继续之前阅读about JUnit。
答案 3 :(得分:1)
我不知道你在学习如何在测试中使用模拟对象走了多远,所以我会写一个简短的描述,然后指出你可能对你有帮助的文章的方向。模拟对象用于单元测试,以替换难以创建或难以进入测试所需状态的外部依赖项。存在的各种模拟框架为您提供了创建“伪”对象的机制,这些对象取代了这些依赖项。这些模拟对象将跟踪从您的代码进入它们的调用,并允许您稍后对这些交互进行断言。有一篇关于模拟对象的知名文章以及它们与“存根”的关系,这是另一种简化外部依赖关系的常用测试策略。它由Martin Fowler编写,可以在这里找到: