I've been trying to do a unit test of my DAO but I haven't find out the way to do it yet and I'm feeling a little desperate. I have a tiny DAO that looks like this:
public interface ElectionsDao {
List<String> getDates();
}
I'm using Spring framework to do DI using SimpleJdbcTemplate. My implementation looks like this:
public class ElectionsDaoImpl extends SimpleJdbcDaoSupport implements ElectionsDao {
public List<String> getDates() {
List<String> dates = new ArrayList<String>();
try {
dates = getSimpleJdbcTemplate().query("SELECT electiondate FROM electiondate", new StringRowMapper());
} catch (DataAccessException ex){
throw new RuntimeException(ex);
}
return dates;
}
protected static final class StringRowMapper implements ParameterizedRowMapper<String> {
public String mapRow(ResultSet rs, int line) throws SQLException {
String string = new String(rs.getString("electiondate"));
return string;
}
}
}
What I want to do is just a unit test of getDates() using EasyMock but I haven't found the way to do it. I'm so confused. Can anybody help me please?
It looks as though getSimpleJdbcTemplate is the biggest problem for unit testing. One way you could test is to extend the class under test and override the getSimpleJdbcTemplate method e.g.
public class ElectionDaoTest {
/** Class under test */
private ElectionsDaoImpl dao;
#Before
public void setUp() {
dao = new ElectionsDaoImpl(){
SimpleJdbcTemplate getSimpleJdbcTemplate(){
// Return easy mock version here.
}
};
}
#Test
// Do tests
}
There may be an easier way with EasyMock, but I'm not that familiar with it.
Thank you for your comments. I decided to do the test using Spring. My test code ended like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="classpath:beans.xml")
public class DBConectionTest{
#Resource
private ElectionsDao electionsDao;
#Test
public void testGetDates(){
List<String> dates = electionsDao.getDates();
assertNotNull(dates);
}
}
I'm using the same xml file that I use when running my project. Hope it helps someone.
Related
Even though I have read the manual and gone through multiple answers for Powermock, could not mock a static method for my use case.
Class:
#Component
public class SCUtil{
public void createSC(){
try {
String host = InetAddress.getLocalHost().getHostAddress();
// ...
// ...
// ...
} catch (UnknownHostException e) {
log.error("Exception in creasting SC");
throw new ServiceException(e);
}
}
}
Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest( InetAddress.class )
public class SCUtilTest {
#InjectMocks
private SCUtil scUtil;
private Event event;
#Before
public void beforeEveryTest () {
event = new InterventionEvent();
}
#Test(expected = ServiceException.class)
public void testCreateSC_Exception () {
PowerMockito.mockStatic(InetAddress.class);
PowerMockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException("test"));
scUtil.createSC(event);
}
}
Here, the test is failing as no exception is being thrown:
java.lang.AssertionError: Expected exception:
com.example.v1.test.selftest.errorhandling.ServiceException
I have wrecked more than a couple of hours in this and still have not gotten it to work. What am I doing wrong?
Thank you for all the help in advance :)
java.net.InetAddress is a system class. The caller of the system class should be defined in #PrepareForTest({ClassThatCallsTheSystemClass.class}).
See documentation.
The way to go about mocking system classes are a bit different than
usual though. Normally you would prepare the class that contains the
static methods (let's call it X) you like to mock but because it's
impossible for PowerMock to prepare a system class for testing so
another approach has to be taken. So instead of preparing X you
prepare the class that calls the static methods in X!
Please note #InjectMocks annotation does not inject static mocks, it can be removed.
Example of working test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(SCUtil.class)
public class SCUtilTest {
private SCUtil scUtil = new SCUtil();
#Test(expected = ServiceException.class)
public void testCreateSC_Exception () throws UnknownHostException {
PowerMockito.mockStatic(InetAddress.class);
PowerMockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException("test"));
scUtil.createSC();
}
}
I have an application with 3 layers:
App <--> Graph <--> Couchbase
I'm trying to test the GraphConnector by mocking the couchbase layer and "replacing" it with a very basic in-memory graph implementation, using the same approach demonstrated in the JMockit tutorial.
This is my test class (pardon the poor indentation, didn't get the hang of it yet):
public class GraphConnectorTest {
public static final class MockCouchbase extends MockUp<ICouchConnector> {
private Map<String, CouchEntry> couch;
#Mock
public void $clinit() {
couch = new HashMap<String, CouchEntry>();
}
#Mock
public void put(CouchEntry entry) {
couch.put(entry.getKey(), entry);
}
#Mock
public CouchEntry get(String key) {
return couch.get(key);
}
}
GraphConnectorImpl graph = new GraphConnectorImpl();
#BeforeClass
public static void setUpClass() {
new MockCouchbase();
}
#Test
public void testPost() throws Exception {
GraphNode node = new GraphNode(GraphNodeType.DOMAIN, "alon.com");
graph.post(node);
GraphNode retNode = graph.getSingleNode(node.getValue(), node.getType());
assertEquals(node.getValue(), retNode.getValue());
assertEquals(node.getType(), retNode.getType());
}
}
And here is my class under test:
public class GraphConnectorImpl implements IGraphConnector {
private static ICouchConnector couch = new CouchConnectorImpl(); // <-- Basic implementation which I don't want the test to execute
#Override
public void post(GraphNode node) {
CouchEntry entry = new CouchEntry(node.getValue(), JsonDocument.create(node.getValue()));
couch.put(entry);
}
#Override
public GraphNode getSingleNode(String nodeName, GraphNodeType nodeType) {
return new GraphNode(nodeType, couch.get(nodeName).getKey());
}
}
For some reason, the class MockCouchbase that I created within the test class isn't automatically bound to the private field ICouchConnector couch of the tested class, as shown in the tutorial. Instead, the real implementation is called, which is obviously undesirable.
If I remove the reference to the real implementation, I just get a good ol' NullPointerException.
I tried playing with the #Tested and #Injectable annotations but to no avail.
Solving my own question.
The problem with the way I wrote the class under test was explicitly invoking the constructor of the real implementation. I'll be surprised if any mocking framework can "bypass" that.
Instead, I should've created a constructor that gets ICouchConnector as one of its arguments, e.g. use dependency injection properly.
public class GraphConnectorImpl implements IGraphConnector {
private static ICouchConnector couch;
public GraphConnectorImpl(ICouchConnector connector) {
couch = connector;
}
// Rest of class...
}
JMockit will then attempt to find a constructor that corresponds to the fields annotated #Tested and #Injectable in the test class.
public class GraphConnectorTest {
#Tested
GraphConnectorImpl graph;
#Injectable
ICouchConnector couch;
// Rest of class...
}
I'm looking to combine the flexibility of Spring Profiles and Configurations with the parallel running of JUnit tests which utilize either the Parameterized or Theories annotation. Is there any way to incorporate all of these features to get my unit tests running?
The problem I keep running into is the parameters need access to an injected bean, which isn't possible since the function annotated with #Parameters or #DataPoints is supposed to be static. I'd really hate to have to wire that into each class or even a static function somewhere because I'd like to quickly be able to switch profiles without having to change Java code. Is this possible?
Found the ticket for this request. It seems the attached file has some issues though. Looks like it's been a feature request for quite some time now.
I've been looking for a solution of this problem too. And there is one ! But as it comes from somebody's blog, I can't take the credit for it however. :-)
Unfortunately I can't find the original blog any more...
#RunWith(Parameterized.class)
#ContextConfiguration("/beans.xml")
public class MyTest {
private final File file;
public MyTest(final File file) {
this.file = file;
}
#Autowired
private PlatformTransactionManager transactionManager;
private TestContextManager testContextManager;
#Parameterized.Parameters
public static Collection<File[]> getFilesToTest() throws Exception {
return getValidFiles();
}
#Before
public void setUpSpringContext() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this); // does the autowiring !
}
#Test
public void testInTransactionContext() throws Exception {
new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status) {
status.setRollbackOnly();
try {
... run the test ...
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
});
}
}
Hello I would like to know what is the best approach to mock void methods for example: I have a PersonManager under the test and then I have dao that is mocked.
class PersonManager {
PersonDao dao...
PersonManager(PersonDao dao)...
Preson find(String person)...
void delete(String person)...
}
class PersonManagerTest {
Map<String, Person> persons ..... = "person1", "person2", "person3";
PersonDao mock...
PersonManager manager = new PersonManager(mock);
//easy one
#Test public void shouldReturnExistingPerson() {
expect(mock.find("person1").andReturn(persons.get(0));
Person result = manager.find("person1");
// replay and verify logic
}
//but what should I do here?
#Test public void shouldDeleteExistingPerson() {
//should I remove a person from testing Map holding test data? or what am I doing wrong
}
}
So testing method with return was easy but how to toset void method? Thank you for suggestions, and Mcokito examples are welcomed too.
}
With easy mock, you don't need to wrap void functions around expect(). You just need to do something like:
obj = createMock(...)
obj.someVoidMethod();
replay(obj);
...
verify(obj);
It depends entirely on what you're trying to test.
In mockito, if you want to check only that the DAO delete method is called with the correct parameter, then verify is what you want.
I would suggest that this is exactly what you want since your unit test for PersonManager should not be testing PersonDao.
When deleting something, I suggest returning the object you just deleted. It makes testing much, much easier and allows doing things after you deleted (e.g. showing notice, logging, etc). I think most (all?) Java collections are doing so.
Mockito provides a static verify method that can verify when you call any method, even those that have void as return type. For your code sample, the following mockito code should work:
// Put this among your import statements
import static org.mockito.Mockito.*
class PersonManagerTest {
private PersonManager manager; // SUT
private Map<String, Person> mockedPersons;
private PersonDao mockDao;
// Don't forget to setup from scratch for each test
#Before public void setup() {
mockDao = mock(PersonDao.class); // mockito mock method
mockedPersons = new HashMap<String, Person>();
for (int i=1; i<=3; i++) {
mockedPersons.put("person"+i, mock(Person.class));
}
manager = new PersonManager(mockDao);
}
// setup dao to return a mocked person
private void whenPersonIsAdded(int i) {
Person personToReturn = mockedPersons.get("person"+i);
when(mockDao.find("person"+i)).thenReturn(personToReturn);
}
#Test public void shouldReturnExistingPerson() {
whenPersonIsAdded(1);
Person expectedPerson = mockPerson;
Person actualPerson = manager.find("person1");
assertEquals(expectedPerson, actualPerson);
}
#Test public void shouldDeleteExistingPerson() {
String expectedPersonString = "person1";
manager.delete(expectedPersonString);
verify(mockDao).delete(expectedPersonString);
}
}
Hope this helps.
I have a Java class that simply extends a library class and calls a method of its parent with a default parameter. How do I write a Junit test for that? A MockObjectTestCase is good too. Here is an example of what I'm talking about:
public class ResourceBundleMessageSource {
public String getMessage(String key, Object[] objects, Locale locale) {
//Spring library method
}
}
public class MessageResource extends ResourceBundleMessageSource {
public String getMessage(String key) {
return (getMessage(key, null, Locale.getDefault());
}
}
I know the wrapper method isn't even necessary, but makes frequent calls to it easier. Note the class works fine, I'm only interested in how the unit test is written.
If you would be willing to refactor your class slightly, I would recommend MessageResource delegate to a MessageSource instance, rather than extend ResourceBundleMessageSource. Then I'd use mocks in my unit test. Something like this:
public class MessageResource implements MessageSource {
private final MessageSource delegate;
public MessageResource(MessageSource delegate) {
this.delegate = delegate;
}
public String getMessage(String key) {
return delegate.getMessage(key, null, Locale.getDefault());
}
// need to implement three other MessageSource methods,
// simple pass-throughs to delegate
}
and unit test
public class MessageResourceTest {
private MessageSource mockDelegate;
private MessageResource messageResource;
#Before
public void setUp() throws Exception {
mockDelegate = //mock with your favorite framework, or by hand
messageResource = new MessageResource(mockDelegate);
}
#Test
public void testGetMessage() {
String key = "foo";
String actualMessage = messageResource.getMessage(key);
assertEquals(key, /* get key passed to mock delegate */ );
assertSame(Locale.getDefault(), /* get Locale passed to mock delegate */);
assertEquals(/*expected message from mock*/, actualMessage);
}
}
For this particular example I probalby would not bother to test it.
If you do need to test it, try something like:
#Test
public void getDefaultMessage() {
ResourceBundleMessageSource origSource = <create source>
MessageResource subSource = <create with same criteria as origSource>
String key = <some key that is locale-specific>
assertEquals(origSource.getMessage(key, null, Locale.getDefault()),
subSource.getMessage(key));
}
If the first two lines are hard to write, then it makes even more sense not to test it.
If you have several tests like this, move the first two lines into a setup fixture.
I don't think it's even worth writing a unit test for that. If there's already a test for ResourceBundleMessageSource.getMessage(), then that should be good enough.