I'm trying to write test a case with mockito for a class that is injected with a ComboPooledDataSource.
I'm got an error saying that ComboPooledDataSource is a final class and cannot be mocked. So, I was thinking of mocking the interface(either DataSource) and using it for the test case but am not sure how to do it.
private Datasource cpds;
private Connection connection;
#Test
public void test() throws Exception {
connection = getConn();
cpds = mock(DataSource.class);
when(cpds.getConnection()).thenReturn(connection);
accessor = new comboPoolUser(cpds);
accessor.setConnection();
}
method in comboPoolUser that calls getConnection:
public void setConnection() {
try {
connection = comboPooledDataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("error",e);
}
}
my "comboPoolUser" constructor takes in a ComboPooledDataSource but I'm trying to mock a "DataSource" for the test so I'm getting a "cannot find symbol: constructor comboPoolUser(javax.sql.DataSource)" error. What's the correct way to do this?
If your ComboPoolUser only requires the methods that are on the DataSource interface, change the constructor so that it takes in a DataSource. Currently the only thing it's doing is getting the connection, so on the face of it it looks possible. Generally, passing dependencies by interface helps maintain encapsulation.
Alternatively, if the ComboPoolUser is your own class, you could write a wrapper around the ComboPoolDataSource, give the wrapper an interface of your own, and make it so think that it's testable by inspection (so every method in the wrapper is just a delegation to the ComboPoolDataSoruce). You can then mock the interface to the wrapper.
Related
I want to test a class that has an "ObjectMapper" as an instance variable:
public class EventTransformerImpl implements EventTransformer {
#Inject
private ObjectMapper objectMapper;
private String convertParametersToJson(NotificationConfig config) {
String parametersAsJson = null;
try {
parametersAsJson = objectMapper.writeValueAsString(config.getOrdinaryParameters());
} catch (IOException e) {
logger.info("There was a problem in writing json:" + config.getParameters(), e);
parametersAsJson = null;
}
return parametersAsJson;
}
}
this class does not have any "setter" or "constructor" for initializing "objectMapper" (it is initialized using "spring"):
<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd'T'HH:mm:ssZ"/>
</bean>
</property>
</bean>
when I want to test "EventTransformerImpl" class, objectMapper has null value, how can I pass "objectMapper" to "EventTransformerImpl" in my unit test class.
This is a typical example where a mock framework, such as Mockito, can help you:
public class TestClass {
#Mock
private ObjectMapper objectMapper;
#InjectMocks
private EventTransformer eventTransformer;
#BeforeMethod
public void setUp() {
eventTransformer = new EventTransformerImpl();
MockitoAnnotations.initMocks(this);
}
}
Here, #Mock and #InjectMocks are parts of the Mockito framework. The magic happens in MockitoAnnotations.initMocks(this) which will scan this, which in this case is TestClass, for these annotations. Mockito initializes objectMapper as a mock, and injects it into eventTransformer. You can then use Mockito to decide how objectMapper should behave.
You can read more about Mockito here.
Also, #BeforeMethod is a TestNG method, analogue with JUnits #Before.
However, many people prefer constructor injection, as proposed by davidxxx. This will make it clearer which dependencies EventTransformerImpl has, and forces it to be initialized with the correct dependencies. By doing this, there is no need to "magically" (I guess Mockito uses reflection under the hood) inject the dependencies, simply initialize the class to be tested by calling the constructor.
Your class could look something like this (here using Spring's #Autowired annotation):
public class EventTransformerImpl implements EventTransformer {
private ObjectMapper objectMapper;
#Autowired
public EventTransformerImpl(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
private String convertParametersToJson(NotificationConfig config) {
String parametersAsJson = null;
try {
parametersAsJson = objectMapper.writeValueAsString(config.getOrdinaryParameters());
} catch (IOException e) {
logger.info("There was a problem in writing json:" + config.getParameters(), e);
parametersAsJson = null;
}
return parametersAsJson;
}
}
This will be less error prone, because with #InjectMocks, Mockito will silently ignore the injection if it fails, while calling a constructor gives the test class full control of the initialization of the test.
For injecting Spring dependencies in JUnit tests and other objects they depend on I use
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:testBeans.xml" })
public class TestRunner {
#Test
public void test1() {
You can provide in-code bean initialization as well
#RunWith(SpringJUnit4ClassRunner.class)
#Configuration
Read more at https://www.mkyong.com/unittest/junit-spring-integration-example/
All three answers are good; so I don't need to repeat the details of those, but I think it is worth to "align" on the "complete" picture.
As shown Spring has built-in means to do injection for unit tests; and you could just go forward and use that. But of course, that means that you are even more "coupling" your business logic code to the Spring framework.
So, if you ever consider re-using your code in a non-Spring situation, then you will find that not only your production code, but also your unit tests will require major rework in order to be used without Spring.
Thus there is a certain merit in the two other answers that suggest to change your production code to enable you to at least fully test your production code without adding a dependency to Spring here.
1) A class should be testable naturally : why not adding a constructor in EventTransformerImpl to inject the mapper ?
You could do something like that in the spring configuration :
<bean id="EventTransformer" class="EventTransformerImpl">
<constructor-arg ref="objectMapper"/>
</bean>
And in the test you could instantiate EventTransformerImpl with a ObjectMapper mocked dependency in the constructor.
2) The other solution is using reflection to inject the field in the class under test in the test method.
You could use the setField() method ofReflectionTestUtils class of Spring to set the dependency or if you didn't use Spring you could have writen a simple utility method to do the job :
public static final void injectValue(String fieldName, Object fieldValue, Object targetObject) {
try {
Field f = targetObject.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
f.set(targetObject, fieldValue);
} catch (Exception e) {
// handle the exception
}
}
I have an internal StreamGobbler class that has 7 methods in it.
I'm looking for a quick way to mock all the methods by default, but override one method named getOutput() (e.g. Partial Mocking).
(full code not shown for clarity)
public class StreamGobbler extends Thread
{
public String getOutput()
public void run()
}
What I would like is to use something like the #Mocked annotation in combination with MockUp to partially mock the getOutput method, but retain all the "default" mocking code on all the other methods. In the docs on partial mocking, it makes the point that if you use MockUp, all non #Mock methods retain their normal functionality. Sometimes that is great, but that isn't what I want in this case.
This is similar to the question JMockit: #Mocke and MockUp combination in the same test, but I can't get away with just looking at method counts.
If I have a test setup like this:
#Test
public void execute(#Mocked StreamGobbler sg)
{
new MockUp<StreamGobbler>()
{
String type = null;
#Mock
void $init(String type)
{
this.type = type;
}
#Mock
String getOutput()
{
if ("OUTPUT".equals(type))
{
return "test output";
}
else
{
return "";
}
}
}
}
I get this error java.lang.IllegalArgumentException: Class already mocked
If I try to add the #Override annotation in the MockUp, it doesn't help (and Eclipse complains about it)
What is the best way to handle this? Use a static class outside this test method?
Using JMockit 1.17, and TestNG
In summary, how do I get every method in StreamGobbler mocked (as with #Mocked), but partially override one method (without manually doing it myself inside the MockUp?)
Full example code which meets the given constraints:
public static class StreamGobbler extends Thread {
public StreamGobbler(String type) {}
public String getOutput() { return null; }
#Override public void run() {}
}
public static class TestedClass {
public String doSomething() throws InterruptedException {
StreamGobbler sg1 = new StreamGobbler("OUTPUT");
sg1.start();
StreamGobbler sg2 = new StreamGobbler("ERROR");
sg2.start();
sg1.join(5000);
sg2.join(5000);
String output1 = sg1.getOutput();
String output2 = sg2.getOutput();
return output1 + '|' + output2;
}
}
#Test
public void useStreamGobbler(#Mocked StreamGobbler sg) throws Exception {
new Expectations() {{
new StreamGobbler("OUTPUT").getOutput(); result = "test output";
new StreamGobbler("ERROR").getOutput(); result = "";
}};
String output = new TestedClass().doSomething();
assertEquals("test output|", output);
}
Firstly, since you are creating an anonymous subclass of the MockUp class, using the #Override annotation would certainly be inappropriate. Those methods that you are providing do not belong to the MockUp class, but the generic you are providing.
Later on during runtime, (through some impressive process (based on what I read here, I'm assuming AOP)) the instance you create in this class will then use your provided method signatures instead of its own.
After reading the API on the Mock class more thoroughly as well as getting some information from JMockit's Getting Started page, I think you're issue lies in a different area entirely. If you have other test methods, they will be interfering with this method.
The error you are getting is saying: "There is already an instance of MockUp declared for the type StreamGobbler, and by calling the Mocked annotation in this test method's parameters and attempting to declare another instance of MockUp with the same generic, you are violating a JMockit stipulation."
I would check to see if you are creating an actual MockUp of StreamGobbler outside of the test method and if so (1) if you want to use it, don't redeclare another instance of MockUp in the method but continue to use the Mocked annotation or (2) if you do not want to use it and you want to re-declare a new instance of MockUp wrapping StreamGobbler, do not use the Mocked annotation in the test method's parameters but keep the MockUp instantiation.
I am new to Guice and have done a lot of reading on this but I have not hand any success with this. I am basically creating a DAO and want to use Guice and the AssistedInjection. Effectively the end goal is create the Injected factory in other classes throughout the application.
Intended use in a actual class that would have the injection of the factory to then get classes from it
public class TestAllModelBootstrap {
#Inject private DAOFactory factory;
public TestAllModelBootstrap() {
}
#Test
public void testGettingDAO() {
Injector injector = Guice.createInjector(new HibernateDAOModule());
Token oToken = new OperTokenV1();
AccountingDAO accountingDAO = factory.create(oToken);
}
}
This is based on Guice-based code of:
public interface DAOFactory {
public AccountingDAO create(Token oTicket);
}
The concrete class has a constructor annoated
#Inject
public HibernateAccountingDAO(#Assisted Token oTicket) {
this.oTicket = oTicket;
}
And the actual Module:
#Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(AccountingDAO.class, HibernateAccountingDAO.class)
.build(DAOFactory.class));
bind(SessionFactoryInterface.class)
.toProvider(HibernateSessionProvider.class);
}
Each time I try to run this:
java.lang.NullPointerException -> indicating that the:
factory.create(oToken);
has factory as a null. In reading up on the problem I was lead to believe that the injection will not work like I am using it in the "test" class. It needs to be put in an "injected" class itself. But this doesn't work either - if I wrapper the Factory injection in another class and then try to use it, it doesn't work.
Any help would be appreciated...
TestAllModelBootstrap did not come from an Injector—JUnit created it instead—so Guice hasn't had a chance to inject it yet. Guice can only inject into objects that it creates via getInstance (and those objects' dependencies, recursively), or objects passed into injectMembers, or existing instances as requested using requestInjection.
You can manually get a factory instance:
factory = injector.getInstance(DAOFactory.class);
Or ask Guice to inject your members using injectMembers:
injector.injectMembers(this); // sets the #Inject factory field
Or use a tool like Guiceberry to inject your test cases across your app.
Is it possible to mock a class object using Mockito and/or PowerMockito?
Something like:
Class<Runnable> mockRunnableClass = mock(Class<Runnable>.class);
An alternative to mocking Class might be to use a Factory instead. I know you are concerned about refactoring, but this could be done without changing the public API of the class. You haven't provided much code to understand the class you are trying to test, but here's an example of refactoring without changing the API. It's a trivial class, but it might give you an idea.
public class Instantiator {
public Runnable getNewInstance(Class<Runnable> runnableClass) throws Exception {
return runnableClass.newInstance();
}
}
Of course, the easiest thing to do to test this trivial class would be to use a genuine Runnable class, but if you tried to mock the Class, you would run into the problems you're having. So, you could refactor it thus:
public class PassThruFactory {
public Object newInstance(Class<?> clazz) throws Exception {
return clazz.newInstance();
}
}
public class Instantiator {
private PassThruFactory factory = new PassThruFactory();
public Runnable getNewInstance(Class<Runnable> runnableClass) throws Exception {
return (Runnable)factory.newInstance(runnableClass);
}
}
Now Instantiator does exactly the (trivially simple) thing it was doing before with the same public API and no need for any client of the class to do any special injecting of their own. However, if you wanted to mock the factory class and inject it, that's very easy to do.
why not using an agent if you can't refactor the code there isn't many options, as #jherics mentionned, java system classes are loaded by the bootstrap classloader and powermock can't redefine their bytecode.
However Powermock now coms with an agent, that will allow system classes mock. Check here for complete explanation.
The main idea is to modify your java command and add :
-javaagent: path/to/powermock-module-javaagent-1.4.12.jar
The basic thing this agent is doing is to definalize classes, to allow future mocking in a specific test, that's why you'll need to use specific types to communicate with the agent, for example with JUnit :
#Rule PowerMockRule rule = new PowerMockRule(); // found in the junit4 rule agent jar
TestNG is also supported. Just check the wiki page for more information.
Hope that helps.
First, as stated in the comments, you would need to do:
Class<Runnable> mockRunnableaClass = (Class<Runnable>)mock(Class.class);
But that won't work in the usual way because of a limitation with PowerMock. You cannot simply mock classes in from java.lang, java.net, java.io or other system classes because they're loaded by Java's bootstrap classloader and cannot be byte-code manipulated by PowerMock's classloader. (See PowerMock FAQ #4.) As of PowerMock 1.2.5, you can work around this. If the class you wanted to test was this:
public class ClassToTest {
private Class<Runnable> runnableClass;
public void setRunnableClass(Class<Runnable> runnableClass) {
this.runnableClass = runnableClass;
}
public Runnable foo() {
return runnableClass.newInstance();
}
}
Then you would do this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ClassToTest.class }) // Prepare the calling class for test
public class SystemClassUserTest {
#Test
public void testFoo() throws Exception {
Class<Runnable> mockClass = (Class<Runnable>) mock(Class.class);
Runnable mockRunnable = mock(Runnable.class);
ClassToTest objectUT = new ClassToTest();
objectUT.setRunnableClass(mockClass);
when(mockClass.newInstance()).thenReturn(mockRunnable);
assertThat(objectUT.foo(), is(sameInstance(mockRunnable);
}
}
How about this. creating a get method of the has a Object (MS) in class PCService and then mock it.
public class PCService implements PCServiceIf {
public MSIf getMS() {
return ms;
}
private MSIf ms = new MS();
public boolean isMovieAccessibleToMyLevel(String myLevel, String movieId) {
return getMS().getPCL(movieId);
}
}
#Test
public void testIsMovieAccessibleToMyLevelMock() {
msMock = mock(MS.class);
spy = spy(new PCService());
doReturn(msMock).when(spy).getMS();
when(msMock.getPCL(movieId)).thenReturn(value);
when(spy.getMS().getPCL(movieId)).thenReturn(value);
assertTrue(spy.isMovieAccessibleToMyLevel("PG", movieId) == true);
}
I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.