Create single WireMockServer object with single port - wiremock

I am very new to Wire mock and gradle. I am planning to setup by using single WireMockServer object with using 8081 port and its configurable in gradle task.
build.gradle
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'com.williamhill.wiremock' version '0.4.1'
id 'java'
}
wiremock {
dir "src/test/resources/"
params "--port=8081"
}
task integrationTest(type: Test) {
runWithWiremock = true
}
test class :
#RunWith(SpringRunner.class)
#SpringBootTest(classes = GladletaskApplication.class)
#AutoConfigureWireMock
#ActiveProfiles(value = "integration")
public class StudentControllerTest {
#Rule
public WireMockRule wireMockRule = new WireMockRule();
#Autowired
public TestRestTemplate testRestTemplate;
#Before
public void setUp() {
mockRemoteService();
}
#Test
public void testAllStudents() {
ResponseEntity<List<Student>> responseEntity = testRestTemplate.exchange("http://localhost:8093/all", HttpMethod.GET,null,
new ParameterizedTypeReference<List<Student>>(){}
);
List<Student> studentList = responseEntity.getBody();
System.out.println("StudentList--->" + studentList.size());
}
private void mockRemoteService() {
stubFor(get(urlEqualTo("/all-students"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBodyFile("response.json")
));
}
}
Now target is i have 8081 server up only once and run all the test cases and shutdown last
is it possible to do it?
could please provide springboot-wiremock gradle custom task?

I have solved by using the following :
1) #BeforeClass & #AfterClass start and stop the server.
2) I tried with a created JUnit test suite and #BeforeClass & #AfterClass start and stop the server, here going apply suite level.

Related

Javax.naming.NameNotFoundException: when trying to look up the jndi name in JavaEE and Wildfly

I am doing some unit testing using javaee and wildly so I am in the client project trying to lookup the jndi name remotely in order to test a service located of course in the ejb, all is fine and the handshake is done correctly but while testing I am getting an exeception which is:
test.ServiceLocatorException: javax.naming.NameNotFoundException:
/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanRemote
Here is a snippet showing the appname, modulename and this is how I am trying to lookup the jndi:
java:global/phenomenon-ear/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanRemote
java:app/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanRemote
java:module/ClientSessionBean!utilities.CllientSessionBeanRemote
java:global/phenomenon-ear/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanLoacal
java:app/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanLoacal
java:module/ClientSessionBean!utilities.CllientSessionBeanLoacal
Client Code:
public class JunitTester {
public static final String jndi = "java:global/phenomenon-ear/phenomenon-ejb/ClientSessionBean!utilities.CllientSessionBeanRemote" ;
private static CllientSessionBeanRemote getProxy() {
return (CllientSessionBeanRemote) ServiceLocator.getInstance().getProxy(jndi);
}
#org.junit.Test
public void Test() throws NamingException {
System.out.println(JunitTester.getProxy().Verify_No_Existence("Multiskan"));}
Any advice could help, thanks.
with your client code I was able to run on glassfish successfully....
Below is the code having said that
if you can test again please give me the exact exception.
Ensure Client.jar is in your classpath in my case its gf-client.jar
server up and running and you than connect the client
Junit
package com.au.clients;
import com.au.ejbs.GreetingI;
import javax.naming.NamingException;
public class JunitTester {
public static final String jndi = "java:global/ejb3_2_ear_exploded/ejb/Greeting";
private static GreetingI getProxy() throws NamingException {
return (GreetingI) ServiceLocator.getInstance().getProxy(jndi);
}
#org.junit.Test
public void Test() throws NamingException {
System.out.println(getProxy().Verify_No_Existence("Multiskan"));
}
}
Service locator
import com.au.ejbs.GreetingI;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class ServiceLocator {
public static ServiceLocator getInstance() {
ServiceLocator serviceLocator = null;
if(serviceLocator == null) {
serviceLocator = new ServiceLocator();
}
return serviceLocator;
}
public static GreetingI getProxy(String jndi) throws NamingException {
InitialContext context =new InitialContext();
GreetingI greeting = context.doLookup(jndi);
return greeting;
}
}
output
true
Process finished with exit code 0

Integration Tests for RESTEasy Endpoint

I want to perform integration tests on my REST endpoint but am running into issues.
Below is my endpoint. NOTE: I cannot change this part of the code.
#Path("/people")
public class PersonResource {
private final PersonService personService;
#Inject
public PersonResource(final PersonService personService) {
this.personService = personService;
}
#GET
#Produces("application/json")
public List<Person> getPersonList() {
return personService.getPersonList();
}
}
From what I've been able to find online, I have the following basic structure for my test.
public class PersonResourceTest {
private Dispatcher dispatcher;
private POJOResourceFactory factory;
#Before
public void setup() {
dispatcher = MockDispatcherFactory.createDispatcher();
factory = new POJOResourceFactory(PersonResource.class);
dispatcher.getRegistry().addResourceFactory(factory);
}
#Test
public void testEndpoint() throws URISyntaxException {
MockHttpRequest request = MockHttpRequest.get("people");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
System.out.print("\n\n\n\n\n" + response.getStatus() + "\n\n\n\n\n");
System.out.print("\n\n\n\n\n" + response.getContentAsString() + "\n\n\n\n\n");
}
}
However, this results in the following error on the last line of the setup method.
java.lang.RuntimeException: RESTEASY003190: Could not find constructor for class: my.path.PersonResource
I explored the Registry API and thought maybe I should have been using addSingletonResource instead, so I changed the last line of setup to dispatcher.getRegistry().addSingletonResource(personResource); and added the following.
#Inject
private PersonResource personResource;
But that results in a NullPointerException on the last line of setup.
The sparse documentation on the mocking isn't very helpful. Can anyone point out where I'm going wrong? Thanks.
You need to do two things
Add a no arguments constructor to your source class:
public PersonResource() {
this(null)
}
In the test class, initialize the PersonResource class with an instance of PersonService class:
dispatcher.getRegistry().addSingletonResource(new PersonResource(new PersonService()));
If needed, the PersonService class can be mocked:
private Dispatcher dispatcher;
#Mock
private PersonService service;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
dispatcher = MockDispatcherFactory.createDispatcher();
PersonResource resource= new PersonResource(service);
ispatcher.getRegistry().addSingletonResource(resource);
}
Hope it helps!

When more than one tests added to rest controller test why am I getting WebApplicationContext is required?

This is very funny. When I ran my controller test with more than one tests I am getting the following error when i run it with maven, but works fine in eclipse Junit.java.lang.IllegalArgumentException: WebApplicationContext is required
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder.<init>(DefaultMockMvcBuilder.java:43)
at org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup(MockMvcBuilders.java:46)
at com.akrilist.rest.web.akripost.controller.AbstractRestControllerTest.setup(AbstractRestControllerTest.java:32)
at com.akrilist.rest.web.akripost.controller.AutoPostControllerTest.setup(AutoPostControllerTest.java:36) Then I ran one test commenting the other alternately (commented testA then run testB, then commented testB then run testA) both are passing. I have no idea what is happening when I put both of then are active tests. if any of you have clue please let me know. I have put my classes here.
AbstractRestControllerTest
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { TestRestServiceConfig.class, WebAppConfig.class })
#WebAppConfiguration
public abstract class AbstractRestControllerTest {
protected MockMvc mockMvc;
#Autowired
protected WebApplicationContext webApplicationContext;
/*#Inject
protected UserAccountService userAccountServiceMock;*/
#Before
public void setup() {
/* Mockito.reset(userAccountServiceMock);*/
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
AutoPostControllerTest
public class AutoPostControllerTest extends AbstractRestControllerTest {
#Autowired
private AutoPostService autoPostServiceMock;
#Autowired
private AutoPostConverter autoPostConverterMock;
#Before
public void setup() {
// Mockito.reset(autoPostServiceMock);
// Mockito.reset(commentPostRepositoryMock);
super.setup();
}
#Test
public void testValidationErrorForNullProfileId() throws Exception {
String description = TestUtil.createStringWithLength(501);
AutoPost autoPost = new TestAutoPostBuilder().description(description).buildModel();
mockMvc.perform(post("/auto/post").contentType(TestUtil.APPLICATION_JSON_UTF8).content(TestUtil.convertObjectToJsonBytes(autoPost))).andExpect(status().isBadRequest())
.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
// .andExpect(jsonPath("$[]", hasSize(1)))
.andExpect(jsonPath("$.type", is("validation failure")));
verifyZeroInteractions(autoPostServiceMock);
}
#Test
public void testGet_shouldReturnPost() throws Exception {
String description = TestUtil.createStringWithLength(501);
String postId = TestUtil.createStringWithLength(16);
Integer profileId = 123456;
TestAutoPostBuilder testAutoPostBuilder = new TestAutoPostBuilder();
AutoPost post = testAutoPostBuilder.postId(postId).description(description).profileId(profileId).buildModel();
when(autoPostServiceMock.get(postId)).thenReturn(post);
when(autoPostConverterMock.convertTo(post)).thenReturn(testAutoPostBuilder.buildDto());
mockMvc.perform(get("/auto/post/" + postId).contentType(TestUtil.APPLICATION_JSON_UTF8)).andExpect(status().isOk()).andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.postId", is(postId))).andExpect(jsonPath("$.profileId", is(profileId))).andExpect(jsonPath("$.links", hasSize(1)));
verify(autoPostServiceMock, times(1)).get(anyString());
verifyNoMoreInteractions(autoPostServiceMock);
}
}
I fixed this issue. It was because of parallel configuration of maven-surefire-plugin. I changed its value to 'classes', so the issue is over. There are two ways we can fix this issue. One is
<parallel>classes</parallel>
<threadCount>10</threadCount>
other way annotating the test class with #net.jcip.annotations.NotThreadSafe that required sequential execution.

Inject Spring bean within RESTEasy Resource at Test time

Within a Unit/Integration Test, I'm trying to use the RESTEasy embedded server TJWSEmbeddedJaxrsServer or POJOResourceFactory inorder to simulate through a MockHttpRequest.get("/data") a resource call for test purpose.
My problem is that based on the use of the server or the Resource factory I'm not able to have a non null instance of spring beans which are injected normally within my resources.
Here's some code for clarification, thanks in advance.
Spring application context :
<context:annotation-config />
<context:component-scan base-package="com.cdcfast.service" />
<bean id="simpleResource" class="com.cdcfast.rest.SimpleResource" />
SimpleResource.java :
#Component
#Path("/data")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class SimpleResource {
#Autowired
private SimpleService service;
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Data> getData() {
return MockDataBase.getInstance().getRows();
}
Unit Test :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:/test/spring/testApplicationContext.xml" })
public class FakeTest {
private Dispatcher dispatcher;
#Before
public void before() {
dispatcher = MockDispatcherFactory.createDispatcher();
POJOResourceFactory noDefaults = new POJOResourceFactory(SimpleResource.class);
dispatcher.getRegistry().addResourceFactory(noDefaults);
}
#Test
public void aTestThatAlwaysPass() throws URISyntaxException {
MockHttpRequest request = MockHttpRequest.get("/data");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assertions.assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
Assertions.assertThat(response.getContentAsString()).isNotNull().isNotEmpty();
}
}
I've had this before because the RESTEasy factories create the POJO rather than Spring so they don't get wired up which can be worked around in the full container but is less easy in a test. The best way around this is to get a handle to your POJO once the factory creates it and then do something similar to this:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(myPojo);
I personally ended up having Spring create the RESTEasy beans using the RESTEasy-Spring plugin and then launching my tests using Jetty, not sure if that is an option for you though.
I exeprienced same problem and i'have solved in similar way as James did:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:spring-context-test.xml" })
public class TestMyService {
Dispatcher dispatcher;
private String username = "user";
#Autowired
ApplicationContext context;
#Before
public void setUp() {
MyService g = new MyService(); //rest service with #autowired spring beans
context.getAutowireCapableBeanFactory().autowireBean(g);
dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(g);
}
#Test
public void TestRest() {
MockHttpRequest request;
try {
request = MockHttpRequest.get("/rest/service").header("LOGON_USER", username);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertTrue("Error, unexpected status code: " + response.getStatus(), response.getStatus() == 200);
LoggerFactory.getLogger(this.getClass()).info("********** " + response.getContentAsString());
} catch (URISyntaxException e) {
Log.error(e.getMessage(), e);
fail(e.getMessage());
}
}
}

Starting Selenium with custom Firefox profile from Eclipse

I'm running Selenium tests from within Eclipse, but I can't load a custom Firefox profile.
Most sources suggest I need to launch the Selenium Server like this:
java -jar selenium-server.jar -firefoxProfileTemplate </path/to/template/>
But when launching my test from within Eclipse it doesn't use that - the tests will run if the Selenium Server isn't running.
This thread suggests that I can set the profile in the DefaultSelenium constructor:
Selenium RC - disabling browser cookie
But the code generated for me by Selenium IDE (Firefox plugin) doesn't use that constructor:
package com.example.tests;
import com.thoughtworks.selenium.*;
import java.util.regex.Pattern;
public class Example extends SeleneseTestCase {
public void setUp() throws Exception {
setUp("http://www.example.com/", "*firefox");
}
public void testExample() throws Exception {
selenium.open("/");
selenium.click("//body");
}
}
Where should I set the DefaultSelenium configuration options? Or is there some other method I can use to load my custom Firefox template?
Thanks!
Stu
I made a SeleniumTestCase that starts/stops the server before/after each test class and starts/stops the Selenium instance before/after each test:
public class SeleniumTestCase {
protected static Selenium selenium;
protected static AppNavUtils appNavUtils;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
SeleniumServerControl.getInstance().startSeleniumServer();
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
SeleniumServerControl.getInstance().stopSeleniumServer();
}
#Before
public void setUp() throws Exception {
// Replace "*chrome" with "*firefox" for Selenium > 1.0
selenium = new DefaultSelenium("localhost", 5444, "*chrome", "http://localhost:8080/");
selenium.start();
appNavUtils = new AppNavUtils(selenium);
}
#After
public void tearDown() throws Exception {
selenium.stop();
}
}
The SeleniumServerControl starts and stops the server:
public class SeleniumServerControl {
private static final SeleniumServerControl instance = new SeleniumServerControl();
public static SeleniumServerControl getInstance()
{
return instance;
}
private SeleniumServer server = null;
protected SeleniumServerControl(){}
public void startSeleniumServer() {
if (server == null) {
RemoteControlConfiguration rcc = new RemoteControlConfiguration();
rcc.setPort(5444);
//rcc.setFirefoxProfileTemplate(newFirefoxProfileTemplate)
server = new SeleniumServer(rcc);
}
server.start();
}
public void stopSeleniumServer()
{
if (server != null) {
server.stop();
server = null;
}
}
}
the version of code you have above assumes that you are running your tests against localhost on port 4444 thats why it is has 2 parameters in the setup.
To set up eclipse to run it you will need to update the run configuration. That is under
Run > Run Configurations
Have a look for the item that has selenium in it and add the config above so that when it runs it will pick it up and run.
I personally just fire up the server when I start working by running a batch file and kill it at the end of the day.