I'm developing an application to perform a series of tests on various web services. These web services consume and produce json, and for each of them we have a class to model the json request and response. For example:
If the json request for serviceX is something like this:
{
"name":"Alex",
"id":"123"
}
We have a class serviceXrequest like this:
public class serviceXrequest {
String name;
String id;
//Constructor, getters/setters, etc
...
}
With an object of that class as the starting point, we can perform a series of test on the web service. The idea is to make those test as generic as possible so they can be used with any web service by just writing a class that models it's request and a class to model the response.
For that reason, all of the test methods developed so far work with plain java objects. This is an example of what I want to have:
public class WebServiceTest {
String serviceURL;
String requestJson;
String requestClass;
String responseClass;
public WebServiceTest() {}
#Test
public static void Test1() { ... }
#Test
public static void Test2() { ... }
....
#Test
public static void TestN() { ... }
}
And then, from another class, invoke those tests with doing something like this:
public class LoginTest { //To test the login web service, for example
public static void main(String[] args) {
WebServiceTest loginTest = New WebServiceTest();
loginTest.setServiceURL("172.0.0.1/services/login");
loginTest.setRequestJson("{"user":"ale","pass":"1234"}");
...
loginTest.runTests();
}
}
I know it's not that simple, but any ideas on how to get there?
Thanks in advance!!
You might also look into REST-assured
One of the best tools for testing your webservices is SOAP UI, but this is more for functional testing
As well I integrated very well FitNesse tests
JMeter goes hand in hand with LoadUI ..kind of same things in terms of stress and load tests for webservices.
Junit...i never used directly applied to the webservice itself.
Most of the times I had a Spring service called by the implemetation of the WebService interface (Port) and I unit tested that one.
You should consider using http-matchers (https://github.com/valid4j/http-matchers) which let's you write JUnit-tests, using regular hamcrest-matchers (bundled with JUnit) to test your web-service via standard JAX-RS interface.
Related
I am trying to write an integration test for JMS service which looks like something like this.
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(Email message) throws InterruptedException {
try {
sendEmail(message);
}catch (Exception e){
LOGGER.log(Level.SEVERE,"Failed to deliver email",e);
Thread.sleep(TimeUnit.SECONDS.toSeconds(Optional.of(retryInterval).orElse(5)));
throw e;
}
}
private void sendEmail(Email message){
...............
}
First of all, can I mock this some how? I tried mocking it, but when I send a message the spring boot application is calling the actual JMS bean not the mock one. Seems like this is not possible.
Even if this is not possible, can I at least aoutowire the bean and somehow check if the receiveMessage method is being invoked. Furthermore, if it is being invoked, the sendEmail part should be faked so that it does not do any work. I have a few ideas such as creating a subclass for testing, but not happy with either of them. So wanted to if you can suggest me a better work around?
One approach is to use different profiles for say development, integration test and production and annotate the different components and your integration test class accordingly.
#Component
#Profile("it")
public class MessageReceiverIT {
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(SimpleMessage email) {
log.info("Integration test pretend to receive {}", email);
// (...)
This is the Integration test that uses the same Application class as the real Application, but if a message is received the MessageReceiverIT.receiveMessage() method will be invoked instead of the production component:
#RunWith(SpringRunner.class)
#SpringBootTest(classes=Application.class)
#ActiveProfiles("it")
public class JmsIntegrationTest {
#Inject
ConfigurableApplicationContext context;
#Test
public void testSend() throws Exception{
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
jmsTemplate.convertAndSend("mailbox", new SimpleMessage("it", "we need more IT"));
// (...)
Also check out Spring Boot Testing for alternative approaches such as the use of #TestConfiguration. I'm using Spring Boot in my examples, but there should be similar approaches if you have a none Spring Boot Application.
i am using spring cloud's eureka and feign to communicate between some services (lets say A and B). Now id like to unittest my service layer of a single service (A). The problem is, that this service (A) is using a feign client to request some information of the other service (B).
Running the unittests without any special configuration throws the following exception: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: service-b => but i do not want any server to run.
My question is: Is there a way to mock the feign client, so i can unittest my service (A) without running an eureka instance and service (B)?
Edit:
I ended up creating a stub for the feign client. The stub is marked as a primary component to force spring instantiating the stub within my tests.
This is the solution i came up with.
//the feign client
#FeignClient("user")
public interface UserClient {
UserEntity getUser();
}
//the implementation i use for the tests
#Component
#Primary //mark as primary implementation
public class UserClientTestImpl implements UserClient {
#Override public UserEntity getUser() {
return someKindOfUser;
}
}
The question is ... do you even need to mock? I often see that people mention "mock" as the first solution to anything that "should not be part of the unit test". Mocking is a technique, not the solution to everything. (see here).
If you are still at the early stages of your code, just refactor and use something else instead of depending on the concrete instance of the Feign Client. You might use an interface, an abstract class, a trait or whatever you want. Don't depend on the object itself, otherwise you have to "mock it".
public interface IWebClient {
public String get(...);
public String post(...);
}
To the question: but I will have other code that will do exactly the same (except that it will be on the concrete instance of Feign), what do I do then?
Well, you can write a functional test and call an instance of a web server that you can setup locally - or use Wiremock, as mentioned by Marcin Grzejszczak in one of the answers.
public class FeignClientWrapper implements IWebClient {
private feign = something
public String get() {
feign.get( ... )
}
public String post() {
feign.post( ... )
}
}
Unit tests are used to test algorithms, if/else, loops: how units work. Don't write code to make mocks fit - it must be the other way around: your code should have less dependencies, and you should mock only when you need to verify the behavior (otherwise you can use a stub or a fake object): do you need to verify the behavior? Do you need to test that a particular method gets called in your code? Or that a particular method gets called with X, Y, and Z for 3 times in a row? Well, then yes, mocking is ok.
Otherwise, use a fake object: what you want is to test just the call/response and maybe the status code. All you probably want is to test how your code reacts to different outputs (e.g., the field "error" is present or not in a JSON response), different status codes (assuming that the Client documentation is right: 200 OK when GET, 201 when POST, etc).
Mocking a feign client is really useful in microservice component tests. You want to test one microservice without having to start all the other microservices.
If you're using Spring (and it looks like you are), the #MockBean annotation together with a bit of Mockito code will do the job.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestYourComponent {
#Configuration
#Import({YourConfiguration.class})
public static class TestConfiguration {
}
#MockBean
private UserClient userClient;
#Test
public void someTest()
{
//...
mockSomeBehavior();
//...
}
private void mockSomeBehavior() {
Mockito.doReturn(someKindOfUser).when(userClient).getUser();
}
}
If you need to use a mock you can use Wiremock to stub the response for a given request - http://wiremock.org/stubbing.html. That way you will do integration tests with real HTTP requests sent. For unit testing the answer from #Markon is very good.
I have a class (lets call it A) that:
In the constructor takes a config and based on it, creates a stub of
a web service and stores a reference to it in a private field.
Has a few methods that call web methods and some stuff inbetween.
I started to create a unit test that:
Creates an instance of a class A with a dummy configuration.
Through reflection it injects the mocked web service stub.
Although that web service has plenty of methods.
Should I mock them all (in every test, with different data)?
Or maybe I should create another layer that encapsulates only the web methods that are being used?
Or there is another approach?
You should create a wrapper interface around your webservice, and make your class under test take a dependency on that interface, rather than directly on the webservice; you can then mock the interface. Only make that interface expose the methods of the webservice that you find interesting. This is known as a facade pattern, and is detailed here.
Without having a clue about what you're testing, aim for something like this:
public interface IWebserviceWrapper
{
Whatever DoStuff(int something);
}
public class WebserviceWrapper : IWebserviceWrapper
{
private WebService _theActualWebservice;
public WebserviceWrapper(Webservice theService)
{
_theActualWebService = theService;
}
public Whatever DoStuff(int something)
{
return _theActualWebservice.DoSomething(something);
}
}
Then your test would look like this (in this case, using MOQ)
public void Test_doing_something()
{
Mock<IWebserviceWrapper> _serviceWrapperMock = new Mock<IWebserviceWrapper>();
_serviceWrapperMock.SetUp(m => m.DoStuff(12345)).Returns(new Whatever());
var classUnderTest = new ClassUnderTest(_serviceWrapperMock.Object);
var result = classUnderTest.Dothings(12345);
Assert.Whatever....
}
Short answer Yes :). Long answer you should use some kind of mocking lib for example: http://code.google.com/p/mockito/ and in your unit test mock the WS stub and pass it to the tested class. That is the way of the force :)
When you unit test a class, you always want to make sure to only test that class and not include its dependencies. To do that, you will have to mock your WS to have it return dummy data when methods are called. Depending on your scenarios, you do not have to mock ALL the methods for each test, I would say only those that are used.
For an example about mocking, you can read this article: http://written-in-codes.blogspot.ca/2011/11/unit-tests-part-deux.html
I am currently building a web application using GWT, GWTP.
And I have some questions about testings:
Is there a Lint-like tool for GWTP or GWT?
How to test presenters? (GWTP with Mockito)
How to test views?
Thanks.
Presenters can be easily unit-tested using Jukito. Here's a quick example of a Presenter being tested using Jukito.
#RunWith(JukitoRunner.class)
public class ShowCommentsPresenterTest {
#Inject
private ShowCommentsPresenter showCommentsPresenter;
#Inject
private PlaceManager placeManager;
#Test
public void onReset_PlaceRequestHasNoShowId_ShouldHideView() {
//given
when(placeManager.getCurrentPlaceRequest()).thenReturn(new PlaceRequest());
//when
showCommentsPresenter.onReset();
//then
verify(showCommentsPresenter.getView()).hide();
}
#Test
public void onReset_PlaceRequestHasAShowId_ShouldDisplayView() {
//given
String someShowId = "12345";
when(placeManager.getCurrentPlaceRequest()).thenReturn(new PlaceRequest()
.with(ParameterTokens.getShowId(), someShowId));
//when
showCommentsPresenter.onReset();
//then
verify(showCommentsPresenter.getView()).display();
}
}
In GWTP's philosophy, Views should not be unit-tested directly. Using a dumb View that is a slave to the Presenter, most of the logic can be tested through unit tests on the Presenters. Tools like Selenium are a better fit for testing UI interactivity.
Google put out a great article about using different testing methodologies with GWT. Definitely check it out. Personally, I use JUnit when I'm testing back-end stuff like business logic, and Selenium for testing the UI and application as a whole from the browser's perspective.
Does anyone know how to run unit tests for Liferay portlets? I have found a lot of posts about it (e.g. http://agile-reflections.opnworks.com/2010/06/portlet-unit-testing-with-liferay-6.html) but none works nonetheless.
This may be overkill, but if you're looking for an Enterprise approach with continuous integration testing, this blog gives a very good example: Continuous integration on Liferay: running your Selenium 2 tests on the Tomcat 6 bundle
Unit testing Liferay portlets is quite complicated when ServiceBuilder is utilized.
The reason is that it generates quite heavy services that contain references not only to beans within Portlet, but even to the Portal beans generated by ServiceBuilder.
There are tools like InitUtil.init(); that lets you at least instantiate and use ServiceBuilder entities... not EntityServices though. For that you'd have to use SpringUtil.loadContext(); that requires
System.setProperty("external-properties", "testing.properties");
where testing.properties contains :
spring.configs=META-INF/ext-spring.xml,\
META-INF/base-spring.xml,\
META-INF/dynamic-data-source-spring.xml,\
META-INF/infrastructure-spring.xml,\
META-INF/shard-data-source-spring.xml,\
META-INF/hibernate-spring.xml,\
META-INF/portlet-spring.xml
These are spring definitions to be loaded for testing application context. It all would be OK, but beans from portlet-spring.xml are those heavy services containing references to Portal bean definitions like ResourceService, UserLocalService, CounterLocalService and you would have to load even META-INF/portal-spring.xml and trust me, it's not that easy cause then you'd have to load quite a lot of other stuff.
THE ANSWER:
The truth is, that you most likely won't have to unit test portlet SB services, never. They represent entities with persistence and service layer around. Something that is not to be tested. You just have to mock them and stub their methods, right ?
And the best way for junit and integration testing as to mocking is not using *LocalServiceUtil static classes in your application, because it is almost unmockable.
You just need to create a Spring FactoryBean :
public class PortalFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortalBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
public class PortletFactoryBean implements FactoryBean {
private Class type;
public void setType(final Class type) {
this.type = type;
}
#Override
public Object getObject() throws Exception {
return PortletBeanLocatorUtil.locate(type.getName());
}
#Override
public Class getObjectType() {
return type;
}
}
<bean id="somePortalBean" class="example.spring.PortalFactoryBean" lazy-init="true">
<property name="type" value="com.liferay.some.util.SomeService"/>
</bean>
<bean id="somePortletBean" class="example.spring.PortletFactoryBean" lazy-init="true">
<property name="type" value="com.example.SomeService"/>
</bean>
#Autowired
private SomeService somePortalBean;
Writing unit/integration tests for this portlet would be quite easy, right ? You just create a spring context for testing and you mock these services :
Using Service Builder is worth it, but you must have some Spring knowledge and play with it for some time. Then it spares a lot of time because it is easy to maintain.
You need to have some third party libraries on classpath.
THe key point is having even portal-impl.jar and other portal dependencies on classpath and having InitUtil.initWithSpring(boolean); load up core spring xml configs that you specify in spring-ext.properties in spring.congigs property, only those services you need. You may need no portal services and only the portlet ones, but this is a problem because your portlet services generated by service builder use the portal services.
Using service builder just needs good knowledge of spring and classloading.
But you need to understand the infrastructure before doing that. There are quite a lot of hacks needed... Like
BeanLocator beanLocator = new BeanLocatorImpl(PortalClassLoaderUtil.getClassLoader(), ac);
PortletBeanLocatorUtil.setBeanLocator("portlet", beanLocator);