Reputation: 309
I create mocked objects and I define some rules (when someMethod()
then doSth()
).
What are the best practices to make that? Create a class with such functionality returning mocked object? Or make a private static method returning mocked object ? Or make my own mocked class?
Upvotes: 3
Views: 5791
Reputation: 41223
If you find yourself creating test classes (other than the classes containing actual tests), then you've defeated the purpose of having a mocking framework.
Create your mocks in your testcases:
@Test
public void testGreetingGenerator() {
Person mockPerson = mock(Person.class);
when(mockPerson.getName()).thenReturn("Alan");
GreetingGenerator greeting = new GreetingGenerator(mockPerson);
assertEquals("Hello Alan", greeting.getGreeting());
}
If you are using the same mock in many tests, by all means make the mock a field, and put the mock creation into an @Before
method.
@Before
public void setUp() {
mockPerson = mock(Person.class);
when(mockPerson.getName()).thenReturn("Alan");
}
@Test
public void testGreetingGenerator() {
GreetingGenerator greeting = new GreetingGenerator(mockPerson);
assertEquals("Hello Alan", greeting.getGreeting());
}
You can create a "basic" mock in setUp()
and add more mocked behaviour to it in the individual testcases. Remember that setUp()
gets called before each test, so you get fresh objects in each test.
If the mock creation gets too long and complex, it's fine to move it into a method (static or otherwise), and if necessary decompose that method into lots of smaller ones.
However, if your test code gets too complicated, think of it as a warning that perhaps the unit under test has too many dependencies and needs to be redesigned for testability.
Mocking is for unit testing. In the example above, the unit I am testing is GreetingGenerator
. I am not intending to test Person
here, so it is better to use a mock Person
than a real one. That way if something about Person
breaks, my Person
tests will fail but my GreetingGenerator
tests will keep working.
However that means that those tests don't validate that your Person and GreetingGenerator classes interoperate properly, and that's why as well as unit tests, you should have integration tests.
If you know a class is just for value objects, there's little benefit in using a mock.
Upvotes: 12