Can someone point me to some examples of Junit or Arquillain tests to test a class that defines a #Produces for a datasource: example of class in Camel project to be tested
/*
* Inject the datasource defined in Fuse's standalone-*.xml file.
*/
#Resource(lookup = "java:jboss/datasources/fang")
private DataSource fangDataSource;
#Produces
#Named("fangDataSource")
public DataSource getDataSourceFang() {
return fangDataSource;
}
Related
My current spring boot testing uses junit5 jupiter. I need to add in request bean.
Following discussion request scoped beans in spring testing, https://github.com/mariuszs/spring-test-web I was able to get it working using JUnit4.
#RunWith(SpringJUnit4ClassRunner.class) //Not OK to remove
#SpringBootTest
#Testcontainers
#ActiveProfiles("test")
public class MainControllerTest {
#Autowired
MyRequestBean myRequestBean;
#Test
public void requestScope() throws Exception {
System.out.println("myRequestBean..." + myRequestBean.getRandom());
}
}
#Component
#RequestScope
#Data
public class MyRequestBean {
int random;
#PostConstruct
public void started() {
random = new Random().nextInt();
System.out.println("Request bean created! random = " + random);
}
}
But myRequestBean is null if I remove
#RunWith(SpringJUnit4ClassRunner.class) I can't keep it since it breaks my current testing using Jupiter
How to get request scope bean testing work in jupiter?
Updated:
I setup a testing project to test above. It might have issue on bring up SpringBootTest. Everything works after I tested in my real project. Spring 5 supports request-scope bean testing.
I am writing a JUnit test for a class which does something like:
org.glassfish.jersey.client.JerseyClient client = getHTTPClient(SSLContextFactory.getContext(), connectTimeout, readTimeout, true);
client.register(CustomJAXBContextProvider.class); // subclass of javax.ws.rs.ext.ContextResolver<JAXBContext>
client.property(MarshallerProperties.JSON_INCLUDE_ROOT, true);
WebTarget webTarget = client.target(contextPath);
Response response = webTarget.request(MediaType.APPLICATION_JSON.get()
return response.readEntity(ResponseModel.class);
The application runs inside a WebLogic container and has another class with a CDI #Produces annotation:
public class ObjectMapperProvider {
private ObjectMapper objectMapper;
#Produces
public ObjectMapper objectMapper() {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JSR310Module());
objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
return objectMapper;
}
}
When I run the JUnit test from outside WebLogic I get an error
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "fieldName" (class ResponseModel), not marked as
ignorable
Because the JSON response contains a field which is not declared in the model and the JUnit is not obtaining the ObjectMapper through the #Produces annotation but getting a default one. The JAXBContext is EclipseLink MOXy.
My question is: How do I get the code tested by my JUint to instantiate ObjectMapper as returned from ObjectMapperProvider instead of a default one lacking the DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false?
We cover this exact scenario using Mockito. Depending on how JaxBContext is created, you could use a spy to return a mock. Without posting your complete test code and the class under test, it's hard to give a more complete answer than that.
I have created a Spring SOAP based webservice which retrives data from my DB , I am able to test the service through SOAP UI , but now I am trying to add few functionalites for the service and I want to add some Junits for the service , Please find my Endpoint and Junit details below.
My End Point Class
#Endpoint
public class CountryEndPoint {
private static final String NAMESPACE_URI = "http://tutorialspoint/schemas";
#Autowired
CountryRepository countryRepository;
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
#ResponsePayload
public GetCountryResponse getCountry(#RequestPayload GetCountryRequest request) throws JDOMException {
Country country = countryRepository.findCountry(request.getName());
GetCountryResponse response = new GetCountryResponse();
response.setCountry(country);
return response;
}
}
Spring-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan
base-package="com.tutorialspoint" />
<sws:annotation-driven />
<bean id="schema"
class="org.springframework.core.io.ClassPathResource">
<constructor-arg index="0" value="*.xsd" />
</bean>
</beans>
Junit-Test calss
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/spring-context.xml")
public class CustomerEndPointTest {
#Autowired
private ApplicationContext applicationContext;
#Autowired
private ResourceLoader resourceLoader;
private MockWebServiceClient mockClient;
private Resource schema = new ClassPathResource("countries.xsd");
#Before
public void createClient() {
mockClient = MockWebServiceClient.createClient(applicationContext);
GenericApplicationContext ctx = (GenericApplicationContext) applicationContext;
final XmlBeanDefinitionReader definitionReader = new XmlBeanDefinitionReader(ctx);
definitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE);
definitionReader.setNamespaceAware(true);
}
#Test
public void testCountryEndpoint() throws Exception {
Resource request = resourceLoader.getResource("request.xml");
Resource response = resourceLoader.getResource("response.xml");
mockClient.sendRequest(withPayload(request)).
andExpect(payload(response)).
andExpect(validPayload(schema));
}
}
I am able to run the test case with out any issue but my problem is I am not able to mock my service class (CountryRepository) mock the the code below.
Country country = countryRepository.findCountry(request.getName());
Does any one have any suggessions on this?
From your test case, I suppose your are trying to mock the CrudRepository object from inside a webservice call: That would be called integration testing. You need to make a choice for unit testing:
Test the request, and assert its response http status code (for example),
Or test the getCountry method inside your CountryEndPoint class. Doing both options at the same time would be considered an integration test.
I will try to answer considering the unit test case, using option 2. I think it will give you better insights for the future.
You are injecting the dependency of the CountryRepository on your CountryEndPoint class. You need to do the same on your testing class. For example, a basic setup would be:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/spring-context.xml")
public class CustomerEndPointTest {
#InjectMocks
private CountryEndPoint countryEndPoint;
#Mock
private CountryRepository countryRepository;
#Test
public void testCountryEndpoint() throws Exception {
Mockito.when(countryRepository //...
countryEndPoint.getCountry(request //build a request object and pass it here.
//assertions...
}
}
Then, whenever a method from CountryRepository is invoked, it will be invoked from the mock instead. This is only possibly because of the injection of the mock via annotations.
If you actually send a request, using a HTTP client (like you intended), you cannot mock the methods being invoked inside your controller class, because you are not manipulating and assigning the instances yourself, and thus are not able to determine what is a mock, and what is not.
I am trying to create a RESTful web service in Karaf 4.0.8 with Apache CXF DOSGI. The service is being called but I am getting this error: No message body writer has been found for class....
Any suggestion is welcome. Thank you!!!
Component:
#Component(immediate = true, property = {
"service.exported.interfaces=*",
"service.exported.configs=org.apache.cxf.rs",
"org.apache.cxf.rs.provider=com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider",
"org.apache.cxf.rs.address=/integr" })
public class AccountRestService implements AccountWebUserIdResource {
...
}
Interface:
------------
#GET
#Produces({
"application/json"
})
AccountWebUserIdResource.GetAccountByWebUserIdResponse getAccountByWebUserId(
#PathParam("webUserId")
String webUserId,
#QueryParam("sc")
String sc,
#QueryParam("fields")
String fields)
throws Exception
;
Entity:
#JsonInclude(JsonInclude.Include.NON_NULL)
#Generated("org.jsonschema2pojo")
#JsonPropertyOrder({
"href",
"crm_member_id",
"email_address",
"account_status"
})
public class Account {
/**
*
* (Required)
*
*/
#JsonProperty("href")
private String href;
/**
*
* (Required)
*
*/
#JsonProperty("crm_member_id")
private String crmMemberId;
/**
*
* (Required)
*
*/
#JsonProperty("email_address")
private String emailAddress;
....
At least with CXF-DOSGi 2 your code probably will not work. Loading the provider from a class name is problematic in OSGi anyway as the CXF DOSGi code has no visibility of the com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider class.
In CXF-DOSGi this can be done using an intent. This is more OSGi friendly as the JacksonJsonProvider is then directly used as a class and so OSGi class loading works nicely. It is also necessary to set a bus property to all to override the jacksonprovider as the spec normally would not allow this.
cxf.bus.prop.skip.default.json.provider.registration=true
The intent class looks like this:
#Component(property = "org.apache.cxf.dosgi.IntentName=jackson")
public class JacksonIntent implements Callable<List<Object>> {
public List<Object> call() throws Exception {
return Arrays.asList((Object)new JacksonJaxbJsonProvider());
}
}
The intents provide a generic way to define features and other overrides for CXF without directly influencing your service class.
The intent then has to be referenced in the service using the service property service.exported.intents=jackson.
I just added a jackson example to CXF-DOSGi.
Another small obstacle is that the current cxf-jackson feature misses a bundle. See CXF-7298.
I'd like to run Surefire in parallel mode (multiple JVMs) where each JVM must run:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
exactly once before the first test. How can this be done?
There are various ways to make some code run at the beginning of a test suite.
Here are 4 (I'm sure there are more):
JUnit via RunWith Suite with Suite.SuiteClasses and BeforeClass (adapted from examples in SuiteTest):
#RunWith(Suite.class)
#SuiteClasses({FirstTest.class, SecondTest.class/*, ...*/, LastTest.class})
public static class AllWithSLF4JBridgeHandler {
#BeforeClass
public static void registerRootLoggerHandlers() {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
TestNG with BeforeSuite:
/**
* Base class for each test class (i.e. every test class should extend this class).
*/
public abstract class BaseTest {
#BeforeSuite
public void registerRootLoggerHandlers() {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
TestNG with Guice:
/**
* Test module. Each test class should be annotated with `#Guice(TestModule.class)`.
*/
public class TestModule implements Module {
#Override
public void configure(Binder binder) {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
Static initialization blocks (test-framework independent):
/**
* Base class for each test class (i.e. every test class should extend this class).
*/
public abstract class BaseTest {
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
}
}
I'm not sure how all of these methods work with Surefire's parallel mode. Methods 1 and 2 may not work there but I believe methods 3 and 4 should.
Another option would be to not use the programmatic installation of the SLF4JBridgeHandler but to use a java.util.logging.config file or class (see LogManager):
"java.util.logging.config.file":
logging.properties file:
// register SLF4JBridgeHandler as handler for the j.u.l. root logger
handlers = org.slf4j.bridge.SLF4JBridgeHandler
System property assignment:
java -Djava.util.logging.config.file=/path/to/logging.properties ...
This works well if you know the path to your logging file beforehand.
"java.util.logging.config.class":
Using a file may not be a good option if you're deploying a WAR and don't know where the file will be, etc. so alternatively you can create a logging config class:
public class SLF4JBridgeHandlerInitializer {
public SLF4JBridgeHandlerInitializer() throws IOException {
String loggingConfigurationString = "handlers = " + SLF4JBridgeHandler.class.getName();
InputStream inputStream = new ByteArrayInputStream(loggingConfigurationString.getBytes());
LogManager.getLogManager().readConfiguration(inputStream);
}
}
System property assignment:
java -Djava.util.logging.config.class=package.SLF4JBridgeHandlerInitializer ...
I've done this before and it has worked well for me (SLF4JBridgeHandler.Initializer by mfulton26 · Pull Request #57 · qos-ch/slf4j).
These final two options should initialize each JVM instance as long as the appropriate system property is set.