I know that if I want to mock a method and assign a specific behavior to it based on its input, I can do it with the MockUps API:
public class DuplicationTest {
static class Duplicator {
public String duplicate(String str) { return null; }
}
@Test
public void verifySameStringReturnedWithMockupsAPI() throws Exception {
new MockUp<Duplicator>() {
@Mock public String duplicate(String str) { return str; }
};
Duplicator dup = new Duplicator();
assertEquals("test", dup.duplicate("test"));
}
}
This test passes.
However, sometimes I don't have the luxury of working with the MockUps API (e.g. when mocking static classes), therefore I can only use the Expectations API:
@Test
public void verifySameStringReturnedWithExpectationsAPI(@Mocked Duplicator dup) throws Exception {
new Expectations() {{
dup.duplicate(anyString); result = anyString;
}};
assertEquals("test", dup.duplicate("test"));
}
This obviously fails. The call to dup.duplicate("test")
returns an empty String
(probably some kind of default). Is there any way around it?
Inspired by a comment made by Rogério, I managed to solve the issue using a Delegate
:
@SuppressWarnings("unused")
@Test
public void verifySameStringReturnedWithExpectationsAPI(@Mocked Duplicator dup) throws Exception {
new Expectations() {{
dup.duplicate(anyString);
result = new Delegate<String>() { String delegate(String str) { return str; }};
}};
assertEquals("test", dup.duplicate("test"));
assertEquals("delegate did it", dup.duplicate("delegate did it"));
}
This is not the most elegant solution and could look a lot better if the Delegate
class was a @FunctionalInterface
(which I understood would happen in the next major release of JMockit).
For now, that seems to be the only way to mock behavior according to the input parameters within the Expectations API.