DAOClass.makeDBConnection() method returns datasource configured (using lookup) in Application Server (Jboss). Need to implement junit test case for this scenario.
Using Mockito, tested the DAO method as follows. As it's not able to find the datasource(as expected), it's returning NullPointerException. How to handle NullPointerException and return the connection which i am creating in below code? OR is there any other better unit test framework which handles this scenario ?
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection("jdbc:sqlserver://DB:1433;DatabaseName=databasename", "userid", "password");
when(DAOClass.makeDBConnection()).thenReturn(conn);
Mockito can't mock static method calls the way you have it; it effectively works by dynamically overriding all methods via a generated subclass (proxy).
You will need to write a wrapper class around static methods that you want to mock, otherwise refactor the code to avoid the static call, or use a tool such as PowerMock to rewrite your system's bytecode at runtime.
Related
I am attempting to use Spock to create an integration test around a Spring application. As it is not a Spring Boot application and the #SpringBootTest annotation interfered significantly with the app's initialization, I am using a minimal configuration.
I specifically need to stub a service in my app that returns objects of type Message; in the actual app these objects would come from a third-party vendor's library and they cannot be instantiated or subclassed, nor do their members have setters, so my only option is to create Stubs for them. However, with this current configuration (I've simplified the test significantly just to get the gist across):
#ContextConfiguration([TestSetup]) // supplies actual Spring beans including some JPA repos
class LogicSpec extends Specification {
#SpringBean
RestService restService = Stub()
#Autowired
ServiceUnderTest sut
#Autowired
SomeJPARepo repository;
def 'should do some business logic'() {
given:
Message m = new Stub() {
getStatus() >> "stubbed status"
}
restService.getMessage(_ as String) >> {
m
}
when:
sut.businessMethod()
then:
// just checking for side effects that `businessMethod` causes, no mocks being matched against
assert repository.findAll().every { it.processed == true }
}
}
}
Internally, the ServiceUnderTest.businessMethod() is using the Message object like this:
restService.getMessage(sid).getStatus() // should be "stubbed status"; always evaluates to null
however, every method of the Message stub always returns null regardless of whether I have defined a behavior for it. The Message objects must return specific values from its getters for the test to work. I would prefer to not have to declare every Message stub as its own #SpringBean; I need to eventually expand the test to use several different Message stub objects. I don't need mocks or spies because the number of invocations of RestService's methods doesn't matter, I just need it to emit proper stubs for ServiceUnderTest to chew on. Apologies if this question is unusual or I've missed something obvious; I'm slightly oblivious to Spock's notion of lifecycle, and the waters have been especially muddied with the addition of the Spring extension.
I discovered the answer soon after writing this, but just for posterity; the third-party Message class is declared as final and thus can't be subclassed; Spock was creating stubs for them but silently failing to add the overridden mock methods. I ended up using PowerMockito to remove this limitation; however this interfered with collecting test coverage metrics, so I instead used a wrapper class that can be mocked and used it everywhere in my code the original Message class was:
public class MessageWrapper {
public MessageWrapper(Message from) {...}
}
it's an extra bit of headache, but it was necessary because test coverage was required in this case. There also seems to be a promising Spock-specific mocking utility that will mock final classes, but I haven't tested it nor do I know if it will interfere with collecting coverage metrics like PowerMockito does.
I'm trying to increase my test coverage so I'm wondering, how would you go about testing for DataAccessExceptions being thrown in a DAO, for example in a simple findAll method which just returns all the data from your data source? In my case, I'm using Spring JdbcTemplates.
For general testing I have my setUp-method with an #Before annotation, mocking the jdbcTemplate used, setting it up in the DAO and mocking all jdbc calls. Now forcing a DataAccessException for something like a create method is pretty simple, just throw the exception when calling a create statement with the right primary keys.
However, I really have no idea how to handle this for methods like simple findAll methods which don't take any input parameters. Testing the valid implementation is straight forward, but how would you go about mocking having no DB connection without it affecting every other test or method?
This would be a concrete implementation of a method I'd like to test:
public List<SomeObject> findAll() throws PersistenceException {
final String sql = "SELECT * FROM SomeObject";
try {
return jdbcTemplate.query(sql, new JdbcSomeObjectMapper());
} catch (DataAccessException ex) {
LOG.error(ex.getMessage());
throw new PersistenceException(ex.getMessage());
}
}
Which would just return all objects in the data source. Testing for a valid call is easy since I can just mock the jdbcTemplate.query call, but I'd never enter the catch block unless there's a connection failure while retrieving the data, and that's what I'd like to test.
Using Mockito you can mock a Class and the method calls of that particular Class. A mocked object can also be asked to throw an exception when particular methods are called on it. First you have to mock your jdbcTemplate, then stub your exception
//mocking JdbcTemplate
JdbcTemplate template = Mockito.mock(JdbcTemplate.class);
Mockito.when(template.query(Mockito.anyString(), (RowMapper<YourClass>) Mockito.any(RowMapper.class))).thenThrow(EmptyResultDataAccessException.class);
//or using EasyMock
EasyMock.expect(template.query(Mockito.anyString(), (RowMapper<YourClass>) Mockito.any(RowMapper.class))).andThrow(new (typeofExecption));
I have the following code:
handler = NodeHandler.getINodeHandler(localZone).getITspPlatformHandler().getITspProcessorManagementHandler();
I mocked this out this way:
mockStatic(NodeHandler.class);
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(NodeHandler.getINodeHandler(localZone)).thenReturn(iNodeHandler);
ITspProcessorManagementHandler iTspProcessorManagementHandler =mock(ITspProcessorManagementHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()).thenReturn(iTspProcessorManagementHandler);
After a few row of code an another chained method call comes:
ITspTrafficProcessor processor = NodeHandler.getINodeHandler(localZone, localUI).getITspPlatformHandler().getITspProcessorManagementHandler()
.getITspProcessorHandler(procs[i]).getITspTrafficProcessorHandler(0).getAttributes();
And i mocked this out this way:
when(NodeHandler.getINodeHandler(localZone,UI.CORBA)).thenReturn(iNodeHandler);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()(+1+).getITspProcessorHandler(anyString())
.getITspTrafficProcessorHandler(anyInt()).getAttributes()).thenReturn(null);
So my question is that, i can not find a better solution than this, because the problem is if i tell the mockito to return null to the handler instead of iTspProcessorManagementHandler then i get a nullpointer exception at (+1+), but if i do the following changes to my code:
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_MOCKS);
Than mockito mocks out every method call, and my when-thenReturn statements does not returns what i want for example null. So any advice to do a better solution????
Messy mocking like that is an indication that you could improve abstraction. I'd consider encapsulating that particular logic in a helper interface/class, or to inject the expected type returned by the "trainwreck" to the method/class.
I have a JUnit class with different methods to perform different tests.
I use Mockito to create a spy on real instance, and then override some method which is not relevant to the actual test I perform.
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
say I have a spy object called 'wareHouseSpy'
say I overriden the method isSomethingMissing :
doReturn(false).when(wareHouseSpy).isSomethingMissing()
What will be the right way to un-override, and bring things back to normal on the spy i.e make the next invokation of isSomethingMissing to run the real method?
something like
doReturn(Mockito.RETURN_REAL_METHOD).when(wareHouseSpy).isSomethingSpy()
or maybe
Mockito.unmock(wareHouseSpy)
Who knows? I couldn't find nothing in that area
Thanks!
Assaf
I think
Mockito.reset(wareHouseSpy)
would do it.
Let's say most of your tests use the stubbed response. Then you would have a setUp() method that looks like this:
#Before
public void setUp() {
wareHouseSpy = spy(realWarehouse);
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
Now let's say you want to undo the stubbed response and use the real implementation in one test:
#Test
public void isSomethingMissing_useRealImplementation() {
// Setup
when(wareHouseSpy.isSomethingMissing()).thenCallRealMethod();
// Test - Uses real implementation
boolean result = wareHouseSpy.isSomethingMissing();
}
It depends whether you are testing with TestNG or JUnit.
JUnit creates a new instance of itself for each test method. You basically don't have to worry about reseting mocks.
With TestNG, you have to reset the mock(s) with Mockito.reset(mockA, mockB, ...) in either an #BeforeMethod or an #AfterMethod
The "normal" way is to re-instantiate things in your "setUp" method. However, if you have a real object that is expensive to construct for some reason, you could do something like this:
public class MyTests {
private static MyBigWarehouse realWarehouse = new MyBigWarehouse();
private MyBigWarehouse warehouseSpy;
#Before
public void setUp() {
warehouseSpy = spy(realWarehouse); // same real object - brand new spy!
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
#Test
...
#Test
...
#Test
...
}
Maybe I am not following but when you have a real object real:
Object mySpy = spy(real);
Then to "unspy" mySpy... just use real.
As per the documentation, we have
reset(mock);
//at this point the mock forgot any interactions & stubbing
The documentation specifies further
Normally, you don't need to reset your mocks, just create new mocks
for each test method. Instead of #reset() please consider writing
simple, small and focused test methods over lengthy, over-specified
tests.
Here's an example from their github repo which tests this behavior and uses it:
#Test
public void shouldRemoveAllInteractions() throws Exception {
mock.simpleMethod(1);
reset(mock);
verifyZeroInteractions(mock);
}
reference : ResetTest.java
Addressing this piece specifically:
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
If you are using JUnit, the cleanest way to do this is to use #Before and #After (other frameworks have equivalents) and recreate the instance and the spy so that no test depends on or is impacted by whatever you have done on any other test. Then you can do the test-specific configuration of the spy/mock inside of each test. If for some reason you don't want to recreate the object, you can recreate the spy. Either way, everyone starts with a fresh spy each time.
I have been having a query regarding writing unit tests for web methods which actually communicates with a database and returns some value.
Say for example I have a web service named "StudentInfoService".
That web serivces provides a API "getStudentInfo(studentid)"
Here is some sample snippet
public class StudentInfoService
{
public StudentInfo getStudentInfo(long studentId) {
//Communicates with DB and creates
// StudentInfo object with necessary information
// and returns it to the caller.
}
}
How do we actually write unit tests for this method getStudentInfo?
Generally how do we write unit tests for methods which involves a connection with a resource(Database, Files, JNDI, etc...)?
Firstly, the class StudentInfoService in your example is not testable, or atleast not easily. This is for a very simple reason - there is no way to pass in a database connection object to the class, at least not in the method that you've listed.
Making the class testable would require you to build your class in the following manner:
public class StudentInfoService
{
private Connection conn;
public StudentInfoService(Connection conn)
{
this.conn = conn;
}
public StudentInfo getStudentInfo(long studentId) {
//Uses the conn object to communicate with DB and creates
// StudentInfo object with necessary information
// and returns it to the caller.
}
}
The above code allows for dependency injection via the constructor. You may use setter injection instead of constructor injection, if that is more suitable, but it usually isn't for DAO/Repository classes, as the class cannot be considered fully formed, without a connection.
Dependency injection would allow your test cases to create a connection to a database (which is a collaborator to your class/system under test) instead of getting the class/system itself to create the collaborator objects. In simpler words, you are decoupling the mechanism of establishing database connections from your class. If your class was previously looking up a JNDI datasource and then creating a connection, then it would have been untestable, unless you deployed it to a container using Apache Cactus or a similar framework like Arquillian, or if you used an embedded container. By isolating the concern of creating the connection from the class, you are now free to create connections in your unit tests outside the class and provide them to the class on a as-needed basis, allowing you to run tests inside a Java SE environment.
This would enable you to use a database-oriented unit testing framework like DbUnit, which would allow you to setup the database in a known state before every test, then pass in the connection to the StudentInfoService class, and then assert the state of the class (and also the collaborator, i.e. the database) after the test.
It must be emphasized that when you unit test your classes, your classes alone must be the only systems under test. Items like connections and datasources are mere collaborators that could and ought to be mocked. Some unit tests would use in-memory databases like H2, HSQL, or Derby for unit-tests and use the production-equivalent installations of databases for integration and functional testing.
Try to use http://www.dbunit.org/intro.html.
Main idea - make a stub database with known dataset to run your tests and assert results.
You will need to reload the dataset before runs to restore initial state.
We are using the in-memory HSQL database. It is very fast and SQL-92 compliant. In order to make our PostgreSQL queries run on HSQL, we rewrite the queries using a self-written test SessionFactory (Hibernate). Advantages over a real database are:
much faster, which is important for unit tests
requires no configuration
runs everywhere, including our continuous integration server
When working with "legacy code", it can be difficult to write unit tests without some level of refactoring. When writing objects, I try to adhere to SOLID. As part of SOLID, the "D" stands for dependency inversion.
The problem with legacy code is that you may already have numerous clients that are using the no arg constructor of StudentInfoService, which can make adding a constructor that takes a Connection conn parameter difficult.
What I would suggest isn't generally best practice, because you're exposing test code in your production system, but it is sometimes optimal for working with legacy code.
public class StudentInfoService {
private final Connection conn;
/**
* This no arg constructor will automatically establish a connection for you. This
* will remain around to support legacy code that depends on a no arg constructor.
*/
public StudentInfoService() throws Exception {
conn = new ConcreteConnectionObject( ... );
}
/**
* This constructor may be used by your unit tests (or new code).
*/
public StudentInfoService( Connection conn ) {
this.conn = conn;
}
public StudentInfo getStudentInfo() {
// this method will need to be slightly refactored to use
// the class variable "conn" instead of establishing its own connection inline.
}
}