I'm trying to learn how to write tests. I'm also learning Java, I was told I should learn/use/practice jMock, I've found some articles online that help to certain extend like :
http://www.theserverside.com/news/1365050/Using-JMock-in-Test-Driven-Development
http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock
And most articles I found was about test driven development, write tests first then write code to make the test pass. I'm not looking for that at the moment, I'm trying to write tests for already existing code with jMock.
The official documentation is vague to say the least and just too hard for me. Does anybody have better way to learn this. Good books/links/tutorials would help me a lot. thank you
EDIT - more concrete question :
http://jeantessier.com/SoftwareEngineering/Mocking.html#jMock - from this article
Tried this to mock this simple class :
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();
}
}
Here is how I tried to create a test/mock :
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));
}});
}
}
It passes the test and basically does nothing, what I wanted is to create a map and check its size, and you know work some variations try to get a grip on this. Understand better trough examples, what else could I test here or any other exercises would help me a lot. tnx
Here is a tutorial about using JUnit and EasyMock (a mocking library I personally find far easier to use than JMock): http://www.michaelminella.com/testing/unit-testing-with-junit-and-easymock.html
Even if you are 100% dedicated to using JMock, the concepts between the two are the same and this should help you understand them better.
The purpose of mocking is that when you test Class A
, which depends on B
and C
, your test of A
uses mock versions of B
and C
to be able to specify their exact behavior rather than using the real implementations of B
and C
in your test of A
. Otherwise you are not testing just the single unit of A
, you are implicitly testing B
and C
as well.
As an author of JMock, I wouldn't start with the technique until you have some experience with TDD. Just start with the basics and get it working. Once you start to experience difficulties with scale and growing a design, come back to the technique.
The Dave Astels book is still a good introduction and the only one, I think, of that generation that explained mocks well. After that, you might (ahem) consider ours, "Growing Object Oriented Software, Guided by Tests"
Discount anyone who tells you it's all about making tests against the file system go faster.
You don't need really mock to test this class as its only collaborator is a Map which you might as well just use as is. Also your class doesn't really do anything (except delegate) which is why you feel like you are not testing much.
A straight test might be (I'm assuming you are using JUnit 4 -- your code is an odd mixture of JUnit 3 and 4
@Test
public void sizeIs0WhenEmpty()
{
Map<Integer, String> map = Collections.emptyMap();
Cache cache = new Cache(map)
assertEquals(0, cache.size());
}
with mocks it would be (assuming the mock code is correct -- I don't use JMock)
@Test
public void sizeIs0WhenEmpty()
{
context.checking(new Expectations() {{
atLeast(1).of(mockMap).size();
will(returnValue(0));
}});
assertEquals(0, cache.size());
}
In both cases you setup the system by setting the map to have the properties you want to test and then check that the cache has the same properties (as it is a straight delegate).
I would recommend you read about JUnit before you continue.
I don't know how far you've gone down the path to learning about using mock objects in testing, so I'll write a brief description then point you in the direction of an article that may be helpful to you. Mock objects are used in unit testing to replace external dependencies that are difficult to create or difficult to get into the state you want them for your test. The various mocking frameworks that exist give you mechanisms to create "fake" objects that take the place of these dependencies. These mock objects will keep track of calls coming into them from your code and allow you to make assertions about these interactions later. There's a well known article about mock objects and how they relate to "stubs", another common testing strategy for simplifying external dependencies. It was written by Martin Fowler and can be found here:
http://martinfowler.com/articles/mocksArentStubs.html