I'm trying to write a Unit Test for camel to check if an exchange property was correctly set based on the response of the external mocked service. However I can get the property after the call as I can't access the original exchange after mocked external service has been called.
public class OutputTest extends CamelBlueprintTestSupport {
#Override
protected String getBlueprintDescriptor() {
return "/OSGI-INF/blueprint/blueprint-camel.xml,/OSGI-INF/blueprint/blueprint-beans.xml";
}
#Override
public boolean isUseAdviceWith() {
return true;
}
#Override
public String isMockEndpointsAndSkip() {
return "wmq:.*|jetty:.*";
}
#Test
public void testCallAndPropertyIsSet() throws Exception {
getMockEndpoint("mock:jetty:http:localhost").expectedBodiesReceived(context.getTypeConverter().convertTo(String.class, new File("src/test/resources/requests/Request.xml")));
getMockEndpoint("mock:jetty:http:localhost").returnReplyBody(new Expression() {
#Override
public <T> T evaluate(Exchange exchange, Class<T> aClass) {
return context.getTypeConverter().convertTo(aClass, new File("src/test/resources/requests/Response.xml"));
}
});
template.sendBody("direct:route1", context.getTypeConverter().convertTo(String.class, new File("src/test/resources/requests/ValidRequest.xml")));
getMockEndpoint("mock:jetty:http:localhost").expectedBodiesReceived();
//How to assert exchange property 'Property1' has been set?
}
Blueprint camel route:
<route id="rav">
<from uri="direct:route1"/>
<to uri="velocity:templates/RequestTemplate.vm"/>
<to uri="jetty:{{integration.service.service1}}?bridgeEndpoint=true"/>
<setProperty propertyName="Property1">
<xpath resultType="java.lang.String">/soapenv:Envelope/soapenv:Body/namespace:element/text()</xpath>
</setProperty>
</route>
There are different ways to do this. You can try to use the MockEndpoint and get the exchange from there. Another approach is:
Exchange exchange = template.send("uri", new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getIn().setBody("");
}
});
Message resp = exchange.getIn();
assertEquals("someproperty", resp.getProperty("propertyName"));
Related
From what I understand about mocking, the test should not go deeper into the bean being mocked. For example the control flow shouldn't go into the function apiService.getSomeData() and instead it should just return the string "Hello there".
But is that how mocking works or does the program keep going deeper and should I be able to see the print statements of getSomeData() in the stdout?
When I actually run the code below, it doesn't go deeper. But is that how it's supposed to work?
Suppose this is the Rest Controller Code:
#RestController
#RequestMapping(value = "/testing")
public class ApiController {
#Autowired
ApiService service;
#PostMapping(path = "/events/notifications",consumes = "application/json", produces = "application/json" )
public ResponseEntity<String> checkMapping(#Valid #RequestBody String someData, #RequestHeader(value="X-User-Context") String xUserContext) throws Exception {
String response = service.getSomeData(someData);
return ResponseEntity.status(HttpStatus.OK).body(response);
}
}
Suppose this is the Controller test code:
#WebMvcTest(ApiController.class)
public class ApiControllerTest {
#Autowired
MockMvc mockMvc;
#Autowired
ObjectMapper mapper;
#MockBean
ApiService apiService;
#Test
public void testingApi() throws Exception {
Mockito.when(apiService.getSomeData("")).thenReturn("Hello there");
MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/testing/events/notifications")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.header("X-User-Context","something")
.content("something");
mockMvc.perform(mockRequest)
.andExpect(status().isBadGateway());
}
}
Suppose this is the Api Service code:
#Service
public class ApiServiceImpl implements ApiService{
#Override
public String getSomeData(String data) throws Exception {
System.out.println("Going deeper in the program flow);
callThisFunction();
return "Some data";
}
public void callThisFunction(){
System.out.println("Going two levels deeper");
}
}
In your test you are not talking to ApiServiceImpl at all, but an instance that is created by mockito and that is also implementing the ApiService interface. Therefore, your implementation of getSomeData() is not executed at all. That's what mocking is about. You create a "mock" implementation (or let a tool like mockito do it for you) of the thing you do not want to be executed and inject it instead of the "real" thing.
I'm trying to unit test an api call made with retrofit and rxjava.
In order to do that i'm mocking the api call object but api calls subscriber won't trigger its onNext method.
ApiCallsTest.java:
//custom object replacing api call response object
Observable<FastRechargeClass[]> apiObservable = Observable.just(fastRechargeList);
InterfaceAPI api = mock(InterfaceAPI.class);
when(retrofitApi.getApiInterface(context)).thenReturn(api); when(api.getLatestTransactions("token")).thenReturn(apiObservable);
apiCalls.getLatestTransactions("token",context);
ApiCalls.java:
public void getLatestTransactions(String token, final Context context) {
String methodName = "getLatestTransactions";
InterfaceAPI api = retrofitApi.getApiInterface(context);
Observable<FastRechargeClass[]> call = api.getLatestTransactions(token);
call.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Observer<FastRechargeClass[]>() {
#Override
public void onSubscribe(Disposable d) {
WriteLog.print("onSubscribe");
}
#Override
public void onNext(FastRechargeClass[] fastRechargeClasses) {
fastRechargeManager.runUpdateFastRechargeDb(fastRechargeClasses);
}
#Override
public void onError(Throwable e) {
logOnFailureRequests(methodName, e.getMessage());
}
#Override
public void onComplete() {
}
});
}
When running test
onSubscribe is being called and it stops
You need to trigger event emission manually. To do this you need to call method
.blockingFirst()
or
.blockingGet()
depends of observable type you are using.
So you have to add
call.blockingGet()
at the end of getLatestTransactions method or this method should return created observable and call blocking get inside a test method.
I'm using Mockito, DBUnit and HSQLDB to unit test my database code. I'm also writing integration tests of course.
I'm having trouble understanding how to inject a mocked DataSource into the system under test (class I'm testing). The DataSource is used for connection pooling, and therefore other classes can call a static method in the same class in order to retrieve an instance of this DataSource. This means that the DataSource is not injected into any constructors, anywhere, and so my tests don't have any constructors to inject the mocked DataSource into.
I'm getting around this by altering the logic of my real code to check if a private variable is null, and if so then use the injected DataSource (bad design since it's only needed for tests), otherwise it calls the static method to retrieve the connection pool's source (better design).
How do I inject a mocked DataSource into a class that doesn't have a constructor set up to accept it, because it can instead just call the static method to retrieve the dependency?
Class to Test
public DBConnection(DBSource dbSource) { // <--- Constructor only required for test purposes :(
this.dbSource = dbSource;
}
public final void createCompsDB() {
Connection conn = null;
Statement statement = null;
try {
if(dbSource==null){
conn = DBSource.getInstance().getConnection();
}else{
conn = dbSource.getConnection(); /** Likely bad design, since dbSource is only NOT null for tests, so that you can inject the mocked datasource :( */
}
statement = conn.createStatement();
statement.executeUpdate("CREATE DATABASE placesdb");
System.out.println("Database created...");
} catch (SQLException e) {
// ...
}
} finally {
// Close Resources...
}
}
}
Test Class -- Test Passes
public class DBConnectionTest {
final Statement statement = mock(Statement.class);
final Connection connection = mock(Connection.class);
final DBSource dataSource = mock(DBSource.class);
#Before
public void setUp() throws SQLException, IOException, PropertyVetoException {
when(dataSource.getConnection()).thenReturn(connection);
when(connection.createStatement()).thenReturn(statement);
}
#Test
public void testCreateCompDBIfNotAlready() throws Exception {
DBConnection dbConnection = new DBConnection(localDB, dataSource); /** This constructor is only needed for testing :( . How do I avoid it since all the classes I need to test don't require the dependency to be injected? */
dbConnection.createCompsDB();
verify(statement).executeUpdate("CREATE DATABASE PLACES");
}
}
DBSource.java
protected DBSource() throws IOException, SQLException, PropertyVetoException {
ds = new BasicDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUsername("user");
ds.setPassword("pass");
ds.setUrl("jdbc:postgresql://localhost:5432/placesdb");
}
public static DBSource getInstance() { // <--- Static method means dependent classes don't need to accept injections
if (datasource == null) {
datasource = new DBSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.ds.getConnection();
}
}
Mocking of the static class methods may be done with PowerMockito.
The test class should be something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(DBSource.class)
public class DBConnectionTest {
#Mock
final Statement statement;
#Mock
final Connection connection;
#Mock
final DBSource dbsource;
#Before
public void setUp() throws SQLException, IOException, PropertyVetoException {
PowerMockito.mockStatic(DBSource.class);
when(DbSource.getInstance()).thenReturn(dbsource);
when(dbsource.getConnection()).thenReturn(connection);
when(connection.createStatement()).thenReturn(statement);
}
#Test
public void testCreateCompDBIfNotAlready() throws Exception {
DBConnection dbConnection = new DBConnection(localDB); // No test-only constructor anymore
dbConnection.createCompsDB();
verify(statement).executeUpdate("CREATE DATABASE PLACES");
}
}
You can read here more about mocking with PowerMock.
I am testing this code.
service.getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Result<Catalog<SoajsProductPreview>>>() {
#Override
public void onError(Throwable e) {
view.showErrorView(e);
}
#Override
public void onNext(Result<Product> products) {
view.showProducts(products)
}
#Override
public void onCompleted() {}
});
Testing that view.showProducts() the mocked service returns results works fine.
I do
when(service.getProducts().thenReturn(someObservable);
Now I want to test that view.ShowErrorView() is called when the service throws an error but I can't find a way to do that:
Obviously the following doesn't compile
when(service.getProducts().thenReturn(someException);
And this throws an exception immediately but doesn't call the Subscriber's onError method
when(service.getProducts().thenReturn(someException);
How can I get Subscriber.onError() called?
when(service.getProducts().thenReturn(Observable.error(someException))
should work. See the documentation starting here.
I'm trying to modify my CXF/Spring based SOAP web service into using interceptors to
capture SoapFaults and convert them into custom exceptions. The goal here is to
present a web client with only instances of my custom exception class when things go wrong,
never a SoapFault.
This is what I've managed to scrape together so far. You'd think there'd be more on
proper error handling in the various tuts and books , oh well.
FormsEndpointException
#XmlAccessorType(XmlAccessType.FIELD)
public class FormsEndpointException extends Exception
{
#XmlElement(name="errMsg")
private String myMsg
...
FormsEndpointImpl
#WebService( endpointInterface="mycorp.forms.web.endpoint.FormsEndpoint")
#org.apache.cxf.interceptor.InInterceptors (interceptors = {"mycorp.forms.web.resolver.MyExceptionInterceptor"})
public class FormsEndpointImpl implements FormsEndpoint
{
#Resource
WebServiceContext context;
FormTemplateService formTemplateService; //injected from bean
// must have default constructor per JAXB
public FormsEndpointImpl() {}
//only need setters
public void setFormTemplateService(FormTemplateService formTemplateService) {
this.formTemplateService = formTemplateService;
}
//methods
#WebMethod public void insertFormTemplate( FormTemplate formTemplate) throws FormsEndpointException
{
try {
formTemplateService.persist(formTemplate);
} catch ( Exception e) {
throw new FormsEndpointException( e.getMessage());
}
}
....
}
MyExceptionInterceptor
public class MyExceptionInterceptor extends AbstractSoapInterceptor
{
//special constructor
public MyExceptionInterceptor()
{
super( Phase.USER_LOGICAL);
}
#Override
public void handleMessage(SoapMessage arg0) throws Fault
{
//left blank for normal stuff
}
//only gets called when unwinding a chain when an exception is called on that chain
// Every exception will be wrapped into a Fault object by CXF
#Override
public void handleFault(SoapMessage arg0)
{
Fault aNewFault = new Fault( arg0.getContent(Exception.class));
aNewFault.setFaultCode( new QName("SNAP"));
aNewFault.setMessage("DAMMIT");
// TODO Auto-generated method stub
// Throwable FormsEndpointException = new FormsEndpointException("Awww");
}
}
application-context.xml
...
<!-- Spring manage ServiceBean -->
<bean id="formsEndpoint" class="mycorp.forms.web.endpoint.FormsEndpointImpl">
<property name="formTemplateService" ref="formTemplateService" />
</bean>
<!-- JAX-WS Service Endpoint -->
<jaxws:endpoint id="formsServiceService" implementor="#formsEndpoint" address="/formsService">
<jaxws:inFaultInterceptors>
<ref class="mycorp.forms.web.resolver.MyExceptionInterceptor" />
</jaxws:inFaultInterceptors>
<jaxws:outFaultInterceptors>
<ref class="mycorp.forms.web.resolver.MyExceptionInterceptor" />
</jaxws:outFaultInterceptors>
</jaxws:endpoint>
...
Question is, what needs to go into handleFault() to throw a new instance of MyException?
TIA,
Still-learning Steve