7

我正在尝试学习如何编写测试。我也在学习 Java,有人告诉我应该学习/使用/练习 jMock,我在网上找到了一些有助于一定程度的文章,例如:

http://www.theserverside.com/news/1365050/Using-JMock-in-Test-Driven-Development

http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock

而且我发现的大多数文章都是关于测试驱动开发的,首先编写测试然后编写代码以使测试通过。我现在不是在寻找那个,我正在尝试使用 jMock 为已经存在的代码编写测试。

官方文档至少可以说含糊不清,对我来说太难了。有没有人有更好的方法来学习这个。好书/链接/教程会对我有很大帮助。谢谢你

编辑 - 更具体的问题:

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

4

4 回答 4

6

这是一个关于使用 JUnit 和 EasyMock(我个人觉得比 JMock 更容易使用的模拟库)的教程:http: //www.michaelminella.com/testing/unit-testing-with-junit-and-easymock.html

即使您 100% 致力于使用 JMock,两者之间的概念也是相同的,这应该有助于您更好地理解它们。

模拟的目的是,当您测试A依赖于Band的 Class 时C,您的测试A使用 and 的模拟版本,B以便C能够指定它们的确切行为,而不是在您的测试中使用Band的真实实现。否则,您不仅在测试 的单个单元,而且还在隐式测试。CAABC

于 2010-05-25T14:35:36.353 回答
3

作为 JMock 的作者,在您对 TDD 有一些经验之前,我不会从该技术开始。只需从基础开始并让它发挥作用。一旦您开始在规模和设计发展方面遇到困难,请回到该技术。

Dave Astels 的书仍然是一个很好的介绍,而且我认为是那一代人中唯一一本很好地解释了 mock 的书。之后,您可能会(咳咳)考虑我们的“以测试为指导的不断发展的面向对象软件”

Discount anyone who tells you it's all about making tests against the file system go faster.

于 2010-05-27T07:34:04.200 回答
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());
}

在这两种情况下,您都可以通过将地图设置为具有要测试的属性来设置系统,然后检查缓存是否具有相同的属性(因为它是直接委托)。

我建议您在继续之前阅读有关 JUnit的信息。

于 2010-05-25T18:16:56.753 回答
1

我不知道您在学习在测试中使用模拟对象的道路上走了多远,所以我将写一个简短的描述,然后为您指明可能对您有帮助的文章的方向。模拟对象在单元测试中用于替换难以创建或难以进入您希望它们进行测试的状态的外部依赖项。现有的各种模拟框架为您提供了创建“假”对象来代替这些依赖项的机制。这些模拟对象将跟踪从您的代码传入它们的调用,并允许您稍后对这些交互进行断言。有一篇众所周知的文章关于模拟对象以及它们如何与“存根”相关,“存根”是另一种用于简化外部依赖项的常见测试策略。

http://martinfowler.com/articles/mocksArentStubs.html

于 2010-05-25T14:14:21.133 回答