How to test class with local connection to EJB - java

I am facing problem with testing class which has implemented some local connection to EJB in the constructor. This connection is used just inside the constructor and sets some private attributes of the instantiated class.
MyClass which I want to test:
public class MyClass {
private String myValue;
public MyClass() throws Exception {
MyBeanLocal local = EJBFactory.getLocal(MyBeanLocal.class);
myValue = local.fetchValue();
}
public void processValue() {
... do some String magic which should be tested ...
}
public String getValue() {
return myValue;
}
}
EJBFactory contains some enhanced lookup (with caching) and can return local or remote connection (remote requires server location).
MyBeanLocal interface
public interface MyLocalBean {
public String fetchValue();
}
And finally my junit class where I want to test MyClass.processValue method:
public class MyClassTest {
private MyClass myClass;
#Before
public void setUp() {
myClass = new MyClass();
}
#Test
public void testProcessValue() {
Assert.assertEquals(myClass.processValue(), "MY EXPECTED VALUE");
}
}
The question is how to test situation when I run JUnits in local machine (or some automatic test machine like Hudson or Jenkins) and bean runs on application server context which is different than my local one. I can't touch to production code, just need to write test.
Actually I don't need to make MyBeanLocal functional, but I need myValue set.
I was thinking about mocking, but I am not familiar with that.

You can use the JMockit mocking API (which I created) for such tests:
public class MyClassTest
{
#Tested MyClass myClass;
#Test
public void processValue() {
new NonStrictExpectations() {
#Mocked EJBFactory fac;
#Mocked MyBeanLocal mb;
{
EJBFactory.getLocal(MyBeanLocal.class); result = mb;
mb.fetchValue(); result = "SOME VALUE";
}
};
assertEquals(myClass.processValue(), "MY EXPECTED VALUE");
}
}
The mocking of EJBFactory may even be omitted, if it still returns an object in the unit testing environment.

When testing classes that involve database connections mocking is usually the best way to go.
There are several frameworks that make mocking objects a lot easier, one of which is Mockito.
You can find more info about it here
Martin Fowler also wrote a good article about when to use mocks and what the difference is between a mock and a stub. Here's a link to the article.

Related

Powermock can't mock static class

I have a class with code similar to :
public class class1{
private static final ConfigurationService config = Util.getInstance(ConfigurationService.class);
private SendQueueMessages sender;
public void start() throws LifecycleException{
LOGGER.info("Starting");
final ActiveMq activemq = config.getConfiguration().getActiveMq();
sender = new SendQueueMessages(activemq.getQueueName());
}
}
Elsewhere in the program Guice is being used to bind the configuration service and Util like so:
Util.register(new ThingICantChange(){
#Override
protected void configure (){
super.configure();
bind(ConfigurationService.class).to(ConfigurationServiceImpl.class).asEagerSingleton();
}
});
Is this possible to unit test? I was initially trying to use JUnit 5 and mockito, but it became apparent that I needed to mock static classes/methods (IoCUtils) and switched to JUnit4 for PowerMock.
I have tried:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Util.class)
public class Class1Test{
#Test
public void canStart(){
mockStatic(Util.class);
when(Util.getInstance(ConfigurationService.class)).thenReturn(new ConfigurationService);
Class1 class = new Class1();
class.start();
//etc.
}
}
However this just gives me an error about Util not prepared for test. Changing mockStatic() to PowerMockito.spy() did get me to the when, but then throws a null pointer error.
I found a solution, though I have mixed feelings about it.
Using the Util.register (the 2nd code block) I registered a configuration service implementation that created the mock objects. This worked and let me test the start() method, but feels kind of against the idea of a unit test.
public class ConfigServiceTest implements ConfigurationService{
#Override
public Configuration getConfiguration() {
Configuration conf = mock(Configuration.class);
ActiveMq amq = mock(ActiveMq.class);
when(amq.getQueueName()).thenReturn("test");
when(amq.getBrokerUrl()).thenReturn("http://127.0.0.1:61616?soTimeout=1000");
when(conf.getActiveMq()).thenReturn(amq);
return conf;
}
//other methods just allowed to return null
}
Then in the test:
Util.register(new thingICantChange(){
#Override
protected void configure (){
super.configure();
bind(ConfigurationService.class).to(ConfigServiceTest.class).asEagerSingleton();
}
});
class1 service = new class1();
service.start();
Assert.assertEquals(true, true);
start is void and not int a new thread so Assert.assertEquals(true,true) is the best anyone around me knew to check that start ran. Mockito/PowerMock times(1) would require a mock of class1 which seems rather counter to a unit test to see IF it can run.

Mocking with anonymous class in Java

I'm learning about dependecy injection and testing with Mockito. And I just found a tutorial where someone explain an application with dependency injection and without dependency injection. This is the link: https://www.journaldev.com/2394/java-dependency-injection-design-pattern-example-tutorial
I have 2 questions:
The first question is about the code that he writes for testing. What kind of mock is that? Don't you need to use #Mock to mock an object?
This is his code for testing:
public class MyDIApplicationJUnitTest {
private MessageServiceInjector injector;
#Before
public void setUp(){
//mock the injector with anonymous class
injector = new MessageServiceInjector() {
#Override
public Consumer getConsumer() {
//mock the message service
return new MyDIApplication(new MessageService() {
#Override
public void sendMessage(String msg, String rec) {
System.out.println("Mock Message Service implementation");
}
});
}
};
}
#Test
public void test() {
Consumer consumer = injector.getConsumer();
consumer.processMessages("Hi Pankaj", "pankaj#abc.com");
}
#After
public void tear(){
injector = null;
}
}
And the second question is about testing the app without dependency injection. I don't understand why he say that: "Testing the application will be very difficult since our application is directly creating the email service instance. There is no way we can mock these objects in our test classes." Why we cannot mock these objects in our test cases.
The first question is about the code that he writes for testing. What kind of mock is that? Don't you need to use #Mock to mock an object?
To mock an object you have to provide an object that has same type i.e behaves the same or is a subtype of the class that object you want to mock. So to mock an object you can use an instance of anonymous class (in your case it would be an object of anaonymous class that extends MyDIApplication) or you can use Mockito with its #Mock annotation which does basically similiar thing. Bascially using #Mock annotation is similiar to doing :
MyDIApplication myDiApplication = Mockito.mock(MyDIApplication.class)
which creates a mock object extending class passed in constructor. Here you may pass interface or class depending on what you want to mock.
When using anonymous class you provide implementation of methods that you want to mock in overriden implementations of methods, but in case of Mockito you provide intender behaviour by using methods like Mockito::when.
And the second question is about testing the app without dependency injection. I don't understand why he say that: "Testing the application will be very difficult since our application is directly creating the email service instance. There is no way we can mock these objects in our test classes." Why we cannot mock these objects in our test cases.
I guess you are refering to this piece of code :
public class MyApplication {
private EmailService email = new EmailService();
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}
Here you create an instance of EmailService as class field. So there is no possibilty you can mock this (although you could use reflection or PowerMock). So you are tightly coupled to EmailService and it is hard to test MyApplication class logic. To be able to test it you can use constructor injection :
public class MyApplication {
private EmailService email;
public MyApplication(EmailService emaliService) {
this.email = emailService;
}
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}
Or setter injection :
public class MyApplication {
private EmailService email;
public void setEmailService(EmailService emailService) {
this.email = emailService;
}
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}

Powermock - mocking static class members

I'm trying to mock the following class which contains some static members
public class ClientFact {
private static final String BASE_URL = Config.getProperty("prop1");
private static final String USERID = Config.getProperty("prop2");
......................
public static Client createClient() throws AppException {
}
}
but i'm running into issues with the static member variables which are populated by Config.getProperty. This class does a read on a properties file like so
public class Config {
...............
public static String getProperty(Param param) {
String value = null;
if (param != null) {
value = properties.getProperty(param.toString());
}
return value;
}
}
I'm trying to mock this call since i dont care about the loaded properties in my test. This is what ive tried
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClientFact.class})
public class MyTests {
#Test
public void test() {
PowerMock.mockStaticPartial(Config.class, "getProperty");
EasyMock.expect(Config.getProperty(EasyMock.anyObject())).andReturn(EasyMock.anyString()).anyTimes();
PowerMock.mockStatic(ClientFact.class);
}
}
but its giving the following error...
java.lang.NoSuchMethodError: org/easymock/internal/MocksControl.createMock(Ljava/lang/Class;[Ljava/lang/reflect/Method;)Ljava/lang/Object;
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2214)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
any ideas what im doign wrong here?
A non-answer: consider not making static calls there.
You see, that directly couples that one class to the implementation of that static method in some other class; for no real reason. (and for the record: it seems strange that a USER_ID String is a static field in your ClientFact class. Do you really intend that all ClientFacts are using the same USER_ID?!)
You could replace that static call with a non-static version (for example by introducing an interface); and then you can use dependency injection to make an instance of that interface available to your class under test. And then all your testing works without the need to Powermock.
Long story short: very often (but not always!) the need to turn to Powermock originates in production code which wasn't written to be testable (like in your case). Thus instead of using the big bad Powermock hammer to "fix" your testing problem, you should consider improving your production code.
You might want to listen to those videos to get a better understanding what I am talking about.

How to test a Jersey rest service using mock objects

I have developed a rest service using Jersey. Now I want to write some integration tests for this web service but since not every class being used from the web service is already implemented I need to mock some of them. For example I have the following class:
public class A {
private String getWeather() {
return null;
}
}
My web service looks like this :
#Path("/myresource")
public class MyResource {
#GET
#Produces("text/plain")
public String getIt() {
A a = new A();
return a.getWeather();
}
}
The problem is that the getWeather function is not ready so I need to mock the return value for this function. But for the integration test where I issue a rest call I don't know how to do that.
Are there any ideas?
To make your design decoupled from A you should pass it in as a parameter to MyResource. Then you can easily mock it by hand or with mockito. With constructor injection it would look like this:
#Path("/myresource")
public class MyResource {
private A a;
public MyResource(A a) {
this.a = a;
}
#GET
#Produces("text/plain")
public String getIt() {
return a.getWeather();
}
}
and you can test it with
#Test
public void shouldGetIt() {
A a = mock(A.class);
when(a.getWeather()).thenReturn("sunny!");
MyResource r = new MyResource(a);
assertThat(r.getIt(), is("sunny!));
}
This makes your design decoupled. MyResource no longer depends on A directly but on anything that looks lik an A. Another benefit is that mockito doesn't mess with you class files. It is your code that is tested - not something that has been generated on the fly.
Many consider injection by constructor to be a bit old school. I am old so I like it.... With spring (a framework I don't recommend that you pick up) you can autowire variables like so:
#Autowire
private A a;
and you don't need the constructor at all. Spring will find a the only implementation of A and insert it in this variable. I prefer explicit programming so I would chose constructor injection any day.
You may be able to achieve this using Power Mockito (https://code.google.com/p/powermock/wiki/MockitoUsage)
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyResource.class })
public class MyResourceTest {
#Test
public void testGetIt()() {
MyResource mr = new MyResource();
//Setup mock
A mockA = PowerMockito.mock(A.class);
String mockReturn = "Some String";
//Stub new A() with your mock
PowerMockito.whenNew(A.class).withAnyArguments().thenReturn(mockA);
PowerMockito.doReturn(mockReturn).when(mockA).getWeather();
String ret = mr.getIt();
//asserts go here
}
}
Note that you can mock a local variable creation using PowerMockito's whenNew - this should take care of your concern for A a = new A() code in getIt() method.

Mocking a class object using Mockito and PowerMockito

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);
}

Categories

Resources