How to test a Jersey rest service using mock objects - java

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.

Related

How to test a service or do it right mock? Java11, Spock Framework

Colleagues, I welcome you all! Tell me how to decide, or how to act. (Java11, SpringBoot, testing - Spock Framework) I need to write a test that will test a class method, the whole problem is that the method of the class under test calls another service through inheritance, which is not declared in the class under test, but in its abstract ancestor. How to test such a story? If this service were declared in the class under test itself, then everything is clear, I would create a mock in the test and pass it to the constructor, but what if this service is located at the ancestor? I am attaching an example code below.
// The class to be tested
#Service
public class ServiceForTest extends AbstractComponent{
public String methodForTest (String s) {
return someService.generateString(s);
}
}
//An abstract class from which the tested one is inherited and which contains the service
public class AbstractComponent {
#Autowired
protected SomeService someService;
}
public interface SomeService {
String generateString(String s);
}
#Service
public class SomeServiceImpl implements SomeService{
#Override
public String generateString(String s) {
return s;
}
}
And below is an example of what I would do if the service was in the class being tested
//TestClass
#Service
public class ServiceForTest extends AbstractComponent{
final SomeService someService;
public ServiceForTest(SomeService someService) {
this.someService = someService;
}
public String methodForTest (String s) {
return someService.generateString(s);
}
}
class test groovy, Spock Framework
class ServiceForTestTest extends Specification {
ServiceForTest serviceForTest
void setup(){
SomeService someServiceMock = Mock(SomeService)
someServiceMock.generateString("TEST") >> "TEST"
serviceForTest = new ServiceForTest(someServiceMock)
}
def "Test for return current value"(){
when:
def methodForTest = serviceForTest.methodForTest("TEST")
then:
methodForTest == "TEST"
}
}
You use #Autowired, i.e. some kind of dependency injection framework such as Spring or Java EE CDI. Those frameworks have testing support. Specifically for Spring testing, Spock has a Spring module which you can use. I am not a Spring user, so I cannot tell you how to exactly do that, but the documentation is pretty good.
As a general answer, even without any framework support you can test this easily, if you follow the convention to put the test into the same package as the class under test. Because the field you want to inject a mock into is protected, it means for the JVM that all subclasses, but also other classes in the same package have access to it. I.e., you can simply set the value:
serviceForTest = new ServiceForTest()
serviceForTest.someService = someServiceMock
Or, more elegantly using a Groovy-style constructor which implicitly sets field values:
serviceForTest = new ServiceForTest(someService: someServiceMock)
Generally, I recommend constructor or setter injection rather than relying on field injection (especially when fields are private), because then with regard to testability you have a strict dependency to your DI framework and cannot easily write unit tests. So if you can refactor, I recommend you to do it. You just noticed that testing such things can be kind of a headache, unless you have a way out like in this particular case with the protected field. But that is not so super refactoring-friendly.

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

How to mock a method call within a method for which i am writing junit test

Could someone help me with mocking a method call within a method
my code is like :
public class Service {
public List<Bean> Filter(Bean bean){
List<Bean> Filtered_List = getUtilityService.getBeanList();
//Do something
return beanList;
}
}
Now i want to write test case for Service class . How can i mock :
List Filtered_List = getUtilityService.getBeanList(); and set values in it.
The clean solution is to extract UtilityService to a field and pass a mock to the constructor.
public class Service {
private UtilityService utilityService;
public Service(UtilityService utilityService) {
this.utilityService = utilityService;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.getBeanList();
//Do something
return beanList;
}
}
You can also introduce a UtilityServiceFactory and have a utilityServiceFactory field in the Service.
public class Service {
private UtilityServiceFactory utilityServiceFactory;
public Service(UtilityServiceFactory utilityService) {
this.utilityServiceFactory = utilityServiceFactory;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.create().getBeanList();
//Do something
return beanList;
}
}
If getUtilityService is located in Service class, there is also a dirty solution: partial mock. But I do not recommend it. It's better to refactor your code and use one of previous approaches.
EDIT:
Constructor injection with #InjectMocks is not the best idea but here you are:
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
//other imports
#RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
#Mock
UtilityService utilityService;
#InjectMocks
Service service = new Service(null);
#Test
public void shouldFilterBeans() throws Exception {
//given
given(utilityService.getBeanList()).willReturn(asList(new Bean()));
//when
List<Bean> result = service.filter(new Bean());
//then
assertThat(result).hasSize(1); //probably you want to check something else
}
}
to test a method including its own parameter and return value, like the Filter method in your code, it's enough to just pass a Bean instance to it, and then assert the returned List<Bean> object equals to your expected result. generally, for this kind of method, i think it's no need to use mock frameworks.
but if you really want to test the getUtilityService().getBeanList() method call, you should refactor your code:
addfield UnitilityService service and its corresponding setter method in your class Service
in your unit test code, inject a mocked service using the setter method to the object under test and given a returning value for its getBeanList() method, then invoke your Filter method, finally, verify the method call. for the detailed implementation, you can refer the answer of #woru.

How to test class with local connection to EJB

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.

Mockito, Testing an object that relies on injected dependencies (Spring)?

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.

Categories

Resources