my function is similar to:
#TestFactory
public Stream<DynamicTest> dynamicTest() throws Exception {
String geocodingAnasJsonTest = properties.getProperty("smart-road.simulator.json.geocoding-it.anas.testSuite.test");
String endpoint = properties.getProperty("smart-road.simulator.endpoint.anasGeocoding");
RequestSpecification request = RestAssured.given().header("Authorization", auth);
request.accept(ContentType.JSON);
request.contentType(ContentType.JSON);
JsonNode jsonObjectArray = JsonMappingUtil.getJsonFileFromPath(geocodingAnasJsonTest);
Stream<JsonNode> elementStream = StreamSupport.stream(Spliterators
.spliteratorUnknownSize(jsonObjectArray.elements(),
Spliterator.ORDERED), false);
return elementStream.map(jsonNode -> DynamicTest.dynamicTest(String.format("Test ID: %s", jsonNode.get("test_name")),
() -> {request.body(jsonNode.get("request").toString());
Response response = request.post(endpoint);
int statusCode = response.getStatusCode();
boolean res = false;
if (statusCode >= 200 && statusCode < 300) {
res = true;
}
try {
assertEquals(true, res, properties.getProperty("smart-road.response.smart-road.message.status.ok"));
logger.info(properties.getProperty("smart-road.response.smart-road.message.status.ok"));
String responseOK=jsonNode.get("response").toString();
assertEquals(responseOK, response.asString(), properties.getProperty("smart-road.response.smart-road.message.status.right-end"));
logger.info(properties.getProperty("smart-road.response.smart-road.message.status.right-end"));
} catch (AssertionFailedError er) {
logger.error(properties.getProperty("smart-road.response.smart-road.message.status.assertion-failed"));
fail("Test Fallito");
Assertions.assertTrue(true);
}
}
)//fine dynamicTest
);//fine map
}//fine metodo
I have 20 children test.
I run test in main:
SummaryGeneratingListener listener = new SummaryGeneratingListener();
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectMethod(Test.class,"dynamicTest"))
.build();
Launcher launcher = LauncherFactory.create();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
Now with summary= listener.getSummary() i dont read all tests result but only count Failed or Successfull test.
How i read all result fail/success for all tests?
I will want a map like this:
TEST_ID - RESULTS
test0001 Success
test0002 Fail
test0003 Success
test0004 Success
test0005 Fail
How i get this? Is possible?
Thanks
Regards
One approach is to create your own implementation of org.junit.platform.launcher.TestExecutionListener and register it with the launcher. You may look at the source code of SummaryGeneratingListener as a first start. You could change executionFinished(..) to build up the map of test results. Here's a sketch:
class MySummaryListener implements TestExecutionListener {
private Map<String, TestExecutionResult.Status> summary = new HashMap<>();
#Override
public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
summary.put(testIdentifier.getDisplayName(), testExecutionResult.getStatus());
}
}
There's probably more you want to do in the listener but it should give you an idea where to start.
Related
I am new to vertx and async programming.
I have 2 verticles communicating via an event bus as follows:
//API Verticle
public class SearchAPIVerticle extends AbstractVerticle {
public static final String GET_USEARCH_DOCS = "get.usearch.docs";
#Autowired
private Integer defaultPort;
private void sendSearchRequest(RoutingContext routingContext) {
final JsonObject requestMessage = routingContext.getBodyAsJson();
final EventBus eventBus = vertx.eventBus();
eventBus.request(GET_USEARCH_DOCS, requestMessage, reply -> {
if (reply.succeeded()) {
Logger.info("Search Result = " + reply.result().body());
routingContext.response()
.putHeader("content-type", "application/json")
.setStatusCode(200)
.end((String) reply.result().body());
} else {
Logger.info("Document Search Request cannot be processed");
routingContext.response()
.setStatusCode(500)
.end();
}
});
}
#Override
public void start() throws Exception {
Logger.info("Starting the Gateway service (Event Sender) verticle");
// Create a Router
Router router = Router.router(vertx);
//Added bodyhandler so we can process json messages via the event bus
router.route().handler(BodyHandler.create());
// Mount the handler for incoming requests
// Find documents
router.post("/api/search/docs/*").handler(this::sendSearchRequest);
// Create an HTTP Server using default options
HttpServer server = vertx.createHttpServer();
// Handle every request using the router
server.requestHandler(router)
//start listening on port 8083
.listen(config().getInteger("http.port", 8083)).onSuccess(msg -> {
Logger.info("*************** Search Gateway Server started on "
+ server.actualPort() + " *************");
});
}
#Override
public void stop(){
//house keeping
}
}
//Below is the target verticle should be making the multiple web client call and merging the responses
.
#Component
public class SolrCloudVerticle extends AbstractVerticle {
public static final String GET_USEARCH_DOCS = "get.usearch.docs";
#Autowired
private SearchRepository searchRepositoryService;
#Override
public void start() throws Exception {
Logger.info("Starting the Solr Cloud Search Service (Event Consumer) verticle");
super.start();
ConfigStoreOptions fileStore = new ConfigStoreOptions().setType("file")
.setConfig(new JsonObject().put("path", "conf/config.json"));
ConfigRetrieverOptions configRetrieverOptions = new ConfigRetrieverOptions()
.addStore(fileStore);
ConfigRetriever configRetriever = ConfigRetriever.create(vertx, configRetrieverOptions);
configRetriever.getConfig(ar -> {
if (ar.succeeded()) {
JsonObject configJson = ar.result();
EventBus eventBus = vertx.eventBus();
eventBus.<JsonObject>consumer(GET_USEARCH_DOCS).handler(getDocumentService(searchRepositoryService, configJson));
Logger.info("Completed search service event processing");
} else {
Logger.error("Failed to retrieve the config");
}
});
}
private Handler<Message<JsonObject>> getDocumentService(SearchRepository searchRepositoryService, JsonObject configJson) {
return requestMessage -> vertx.<String>executeBlocking(future -> {
try {
//I need to incorporate the logic here that adds futures to list and composes the compositefuture
/*
//Below is my logic to populate the future list
WebClient client = WebClient.create(vertx);
List<Future> futureList = new ArrayList<>();
for (Object collection : searchRepositoryService.findAllCollections(configJson).getJsonArray(SOLR_CLOUD_COLLECTION).getList()) {
Future<String> future1 = client.post(8983, "127.0.0.1", "/solr/" + collection + "/query")
.expect(ResponsePredicate.SC_OK)
.sendJsonObject(requestMessage.body())
.map(HttpResponse::bodyAsString).recover(error -> {
System.out.println(error.getMessage());
return Future.succeededFuture();
});
futureList.add(future1);
}
//Below is the CompositeFuture logic, but the logic and construct does not make sense to me. What goes as first and second argument of executeBlocking method
/*CompositeFuture.join(futureList)
.onSuccess(result -> {
result.list().forEach( x -> {
if(x != null){
requestMessage.reply(result.result());
}
}
);
})
.onFailure(error -> {
System.out.println("We should not fail");
})
*/
future.complete("DAO returns a Json String");
} catch (Exception e) {
future.fail(e);
}
}, result -> {
if (result.succeeded()) {
requestMessage.reply(result.result());
} else {
requestMessage.reply(result.cause()
.toString());
}
});
}
}
I was able to use the org.springframework.web.reactive.function.client.WebClient calls to compose my search result from multiple web client calls, as against using Future<io.vertx.ext.web.client.WebClient> with CompositeFuture.
I was trying to avoid mixing Springboot and Vertx, but unfortunately Vertx CompositeFuture did not work here:
//This method supplies the parameter for the future.complete(..) line in getDocumentService(SearchRepository,JsonObject)
private List<JsonObject> findByQueryParamsAndDataSources(SearchRepository searchRepositoryService,
JsonObject configJson,
JsonObject requestMessage)
throws SolrServerException, IOException {
List<JsonObject> searchResultList = new ArrayList<>();
for (Object collection : searchRepositoryService.findAllCollections(configJson).getJsonArray(SOLR_CLOUD_COLLECTION).getList()) {
searchResultList.add(new JsonObject(doSearchPerCollection(collection.toString(), requestMessage.toString())));
}
return aggregateMultiCollectionSearchResults(searchResultList);
}
public String doSearchPerCollection(String collection, String message) {
org.springframework.web.reactive.function.client.WebClient client =
org.springframework.web.reactive.function.client.WebClient.create();
return client.post()
.uri("http://127.0.0.1:8983/solr/" + collection + "/query")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(message.toString()))
.retrieve()
.bodyToMono(String.class)
.block();
}
private List<JsonObject> aggregateMultiCollectionSearchResults(List<JsonObject> searchList){
//TODO: Search result aggregation
return searchList;
}
My use case is the second verticle should make multiple vertx web client calls and should combine the responses.
If an API call falls, I want to log the error and still continue processing and merging responses from other calls.
Please, any help on how my code above could be adaptable to handle the use case?
I am looking at vertx CompositeFuture, but no headway or useful example seen yet!
What you are looking for can done with Future coordination with a little bit of additional handling:
CompositeFuture.join(future1, future2, future3).onComplete(ar -> {
if (ar.succeeded()) {
// All succeeded
} else {
// All completed and at least one failed
}
});
The join composition waits until all futures are completed, either with a success or a failure.
CompositeFuture.join
takes several futures arguments (up to 6) and returns a future that is succeeded when all the futures are succeeded, and failed when all the futures are completed and at least one of them is failed
Using join you will wait for all Futures to complete, the issue is that if one of them fails you will not be able to obtain response from others as CompositeFuture will be failed. To avoid this you should add Future<T> recover(Function<Throwable, Future<T>> mapper) on each of your Futures in which you should log the error and pass an empty response so that the future does not fail.
Here is short example:
Future<String> response1 = client.post(8887, "localhost", "work").expect(ResponsePredicate.SC_OK).send()
.map(HttpResponse::bodyAsString).recover(error -> {
System.out.println(error.getMessage());
return Future.succeededFuture();
});
Future<String> response2 = client.post(8887, "localhost", "error").expect(ResponsePredicate.SC_OK).send()
map(HttpResponse::bodyAsString).recover(error -> {
System.out.println(error.getMessage());
return Future.succeededFuture();
});
CompositeFuture.join(response2, response1)
.onSuccess(result -> {
result.list().forEach(x -> {
if(x != null) {
System.out.println(x);
}
});
})
.onFailure(error -> {
System.out.println("We should not fail");
});
Edit 1:
Limit for CompositeFuture.join(Future...) is 6 Futures, in the case you need more you can use: CompositeFuture.join(Arrays.asList(future1, future2, future3)); where you can pass unlimited number of futures.
I am trying to do a unit test for the code below. I am able to test the exception block but unable to test the below block as I am getting an exception.
How can I mock or set values to the ListTopicsResult topics = client.listTopics(), so that the flow goes into the if block?
if(!topics.names.get().isEmpty()) { response = true; }
public boolean isBrokerRunning() {
boolean response = false;
Properties property = new Properties();
try(AdminClient client = KafkaAdminClient.create(property)) {
ListTopicsResult topics = client.listTopics();
if(!topics.names.get().isEmpty()) {
response = true;
}
} catch(Exception ex) {
response = false;
}
}
KafkaAdminClient.create
This is a static function call, so you need to mock static function, You can use powermockit on top of mockito to mock static functions.
see this example
use mockito-inline can do this. need some trick
#Test
public void mockCreateAdmin() {
AdminClient mock = mock(KafkaAdminClient.class);
try (MockedStatic<Admin> staticMock = mockStatic(Admin.class)) {
staticMock.when(() -> Admin.create(any(Properties.class))).thenReturn(mock);
KafkaAdminClient adminClient = (KafkaAdminClient) KafkaAdminClient.create(new Properties());
// when
// then
assertEquals(mock, adminClient);
}
}
From below piece of code I am not able to mock checkAccountStatus and its coming as null. What changes do I need to do to resolve this issue?
Class
public AccessIDSearchResponse searchAccessID(AccessIDSearchRequest accessIDRequest) {
String[] productTypes = accessIDRequest.getProductTypes();
AccountResponse actResponse = checkAccountStatus(accessIDRequest);
System.out.println("Response is---->"+JsonService.getJsonFromObject(actResponse));
if (accessIDRequest.getSearchtype().equalsIgnoreCase("accountId") && !Utility.isEmpty(actResponse)
&& !"FREEVIEW".equalsIgnoreCase(actResponse.getAccountStatus())) {
errorHandler.error(ErrorMessages.EPO_EXISTINGTV_ERR_07, ErrorMessages.ACCESS_ID_NOT_FOUND);
}
}
public AccountResponse checkAccountStatus(AccessIDSearchRequest request) {
AccessIDSearchResponse response = new AccessIDSearchResponse();
SearchAccessIdContent content = new SearchAccessIdContent();
DTVNAccountDetails accountDetails = new DTVNAccountDetails();
accountDetails.setAccountNumber(request.getSearchvalue());
List<DTVNAccountDetails> list = new ArrayList<>();
list.add(accountDetails);
content.setDtvAccountList(list);
response.setContent(content);
return helper.getAccountStatus(response);
}
Helper
public AccountResponse getAccountStatus(AccessIDSearchResponse accessIDResponse) {
AccountResponse accountResponse = null;
AccountRequest request = new AccountRequest();
Account account = new Account();
account.setCustomerID(accessIDResponse.getContent().getDtvAccountList().get(0).getAccountNumber());
request.setAccount(account);
String response = dtvnClients.callandGetDtvnStatus(request);
System.out.println("Response is--->"+response);
if (!Utility.isEmpty(response)) {
accountResponse = JqUtil.runJqQueryAndGetString(".content.accountResponse", response,
AccountResponse.class);
if (!Utility.isEmpty(accountResponse) && accountResponse.isSubscribable()
&& !Utility.isEmpty(accountResponse.getAccountStatus())
&& accountResponse.getAccountStatus().equalsIgnoreCase("FREEVIEW")) {
return accountResponse;
}
}
return accountResponse;
}
Test Class
#Test(expected = ServiceException.class)
public void test_searchAccessID_3_sample() throws Exception {
AccessIDSearchRequest request = new AccessIDSearchRequest();
CommonData commonData = new CommonData();
commonData.setAppName("IDSE");
commonData.setLoginId("qay_slid_sr1281");
request.setCommonData(commonData);
request.setSearchtype("accountId");
request.setSearchvalue("qay_slid_sr1281");
request.setMode("abc");
SearchAccessIdContent content = new SearchAccessIdContent();
AccountResponse accountResponse = new AccountResponse();
accountResponse.setAccountStatus("Sucess");
accountResponse.setSubscribable(true);
Mockito.when(helper.getAccountStatus(accessIDResponse)).thenReturn(accountResponse);
Mockito.when(service.checkAccountStatus(request)).thenReturn(accountResponse);
service.searchAccessID(header, request);
}
Your mocks are not properly configured.
When you call
service.searchAccessID(header, request);
it was make the underlying call
checkAccountStatus(request);
(which is correctly mocked and returns accountResponse), but this one does instanciate its result object, so your first mock will never be triggered.
Updating your first mock to something more permissive will probably fix your problem
Mockito.when(helper.getAccountStatus(any(AccessIDSearchResponse.class))).thenReturn(accountResponse);
To be honest, your code is hardly testable because you instanciate too many objects everywhere. Going for mocks here will be a pain in the future when you refactor something. If I were you I would rewrite this piece of code using a TDD approach and favorizing more testable patterns.
First, I want to say thanks to everyone that took their time to help me figure this out because I was searching for more than a week for a solution to my problem. Here it is:
My goal is to start a custom workflow in Alfresco Community 5.2 and to set some custom properties in the first task trough a web script using only the Public Java API. My class is extending AbstractWebScript. Currently I have success with starting the workflow and setting properties like bpm:workflowDescription, but I'm not able to set my custom properties in the tasks.
Here is the code:
public class StartWorkflow extends AbstractWebScript {
/**
* The Alfresco Service Registry that gives access to all public content services in Alfresco.
*/
private ServiceRegistry serviceRegistry;
public void setServiceRegistry(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
#Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
// Create JSON object for the response
JSONObject obj = new JSONObject();
try {
// Check if parameter defName is present in the request
String wfDefFromReq = req.getParameter("defName");
if (wfDefFromReq == null) {
obj.put("resultCode", "1 (Error)");
obj.put("errorMessage", "Parameter defName not found.");
return;
}
// Get the WFL Service
WorkflowService workflowService = serviceRegistry.getWorkflowService();
// Build WFL Definition name
String wfDefName = "activiti$" + wfDefFromReq;
// Get WorkflowDefinition object
WorkflowDefinition wfDef = workflowService.getDefinitionByName(wfDefName);
// Check if such WorkflowDefinition exists
if (wfDef == null) {
obj.put("resultCode", "1 (Error)");
obj.put("errorMessage", "No workflow definition found for defName = " + wfDefName);
return;
}
// Get parameters from the request
Content reqContent = req.getContent();
if (reqContent == null) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing request body.");
}
String content;
content = reqContent.getContent();
if (content.isEmpty()) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Content is empty");
}
JSONTokener jsonTokener = new JSONTokener(content);
JSONObject json = new JSONObject(jsonTokener);
// Set the workflow description
Map<QName, Serializable> params = new HashMap();
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Workflow started from JAVA API");
// Start the workflow
WorkflowPath wfPath = workflowService.startWorkflow(wfDef.getId(), params);
// Get params from the POST request
Map<QName, Serializable> reqParams = new HashMap();
Iterator<String> i = json.keys();
while (i.hasNext()) {
String paramName = i.next();
QName qName = QName.createQName(paramName);
String value = json.getString(qName.getLocalName());
reqParams.put(qName, value);
}
// Try to update the task properties
// Get the next active task which contains the properties to update
WorkflowTask wfTask = workflowService.getTasksForWorkflowPath(wfPath.getId()).get(0);
// Update properties
WorkflowTask updatedTask = workflowService.updateTask(wfTask.getId(), reqParams, null, null);
obj.put("resultCode", "0 (Success)");
obj.put("workflowId", wfPath.getId());
} catch (JSONException e) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
e.getLocalizedMessage());
} catch (IOException ioe) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Error when parsing the request.",
ioe);
} finally {
// build a JSON string and send it back
String jsonString = obj.toString();
res.getWriter().write(jsonString);
}
}
}
Here is how I call the webscript:
curl -v -uadmin:admin -X POST -d #postParams.json localhost:8080/alfresco/s/workflow/startJava?defName=nameOfTheWFLDefinition -H "Content-Type:application/json"
In postParams.json file I have the required pairs for property/value which I need to update:
{
"cmprop:propOne" : "Value 1",
"cmprop:propTwo" : "Value 2",
"cmprop:propThree" : "Value 3"
}
The workflow is started, bpm:workflowDescription is set correctly, but the properties in the task are not visible to be set.
I made a JS script which I call when the workflow is started:
execution.setVariable('bpm_workflowDescription', 'Some String ' + execution.getVariable('cmprop:propOne'));
And actually the value for cmprop:propOne is used and the description is properly updated - which means that those properties are updated somewhere (on execution level maybe?) but I cannot figure out why they are not visible when I open the task.
I had success with starting the workflow and updating the properties using the JavaScript API with:
if (wfdef) {
// Get the params
wfparams = {};
if (jsonRequest) {
for ( var prop in jsonRequest) {
wfparams[prop] = jsonRequest[prop];
}
}
wfpackage = workflow.createPackage();
wfpath = wfdef.startWorkflow(wfpackage, wfparams);
The problem is that I only want to use the public Java API, please help.
Thanks!
Do you set your variables locally in your tasks? From what I see, it seems that you define your variables at the execution level, but not at the state level. If you take a look at the ootb adhoc.bpmn20.xml file (https://github.com/Activiti/Activiti-Designer/blob/master/org.activiti.designer.eclipse/src/main/resources/templates/adhoc.bpmn20.xml), you can notice an event listener that sets the variable locally:
<extensionElements>
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
</activiti:string>
</activiti:field>
</activiti:taskListener>
</extensionElements>
Usually, I just try to import all tasks for my custom model prefix. So for you, it should look like that:
import java.util.Set;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.apache.log4j.Logger;
public class ImportVariables extends AbstractTaskListener {
private Logger logger = Logger.getLogger(ImportVariables.class);
#Override
public void notify(DelegateTask task) {
logger.debug("Inside ImportVariables.notify()");
logger.debug("Task ID:" + task.getId());
logger.debug("Task name:" + task.getName());
logger.debug("Task proc ID:" + task.getProcessInstanceId());
logger.debug("Task def key:" + task.getTaskDefinitionKey());
DelegateExecution execution = task.getExecution();
Set<String> executionVariables = execution.getVariableNamesLocal();
for (String variableName : executionVariables) {
// If the variable starts by "cmprop_"
if (variableName.startsWith("cmprop_")) {
// Publish it at the task level
task.setVariableLocal(variableName, execution.getVariableLocal(variableName));
}
}
}
}
Hello I am using a webservice which returns a output upon completion of code execution. Is it possible that webservice may return the status in chunks like custom strings: Test Started, Test In Progress, Test Completed etc.
What I need to do to achieve this. Here is my current code where I am expecting a json string as input, supplied json is parsed and further processing is being performed.
//Class
public class WebserviceClient
{
/** calling constructor to initialize logger */
Utils c = new Utils();
Logger logger = Logger.getLogger(WebserviceClient.class.getName());
#Path("/test")
#POST
#Consumes(MediaType.APPLICATION_JSON)
//#Produces(MediaType.APPLICATION_JSON)
public String processRequest(final String inputData)
{
String executionID = "NOT_FOUND" ;
String result = "";
try
{
/** creating a pool of threads to submit a task to a callable thread */
ExecutorService ex = Executors.newFixedThreadPool(5);
Future<String> futureObject = ex.submit(new Callable<String>() {
#Override
public String call() throws Exception
{
logger.info("Parsing Received Request: "+inputData);
String rID = new JSONObject(inputData).getString("id");
logger.info("Received Id: "+rID + " From Request: "+inputData);
if(new RunTest().isTestCompleted(rID))
{
return rID;
}
else
{
return "777";
}
}
});
result = futureObject.get();
if(futureObject.get()!=null)
{
ex.shutdown();
}
else{
logger.debug("call id: "+executionID +" result is not generated yet. ");
}
logger.info("call id && Result: "+result);
}
catch(Exception e)
{
logger.error("call id: "+executionID, e);
}
return result;
}
}
You need to do a continuous polling to the server at high frequency to achieve the current status.
For little more information have a look at the :
Continuous polling of output using spring ,rest and angular js
This includes design consideration of using WebSockets etc, but there is no straight forward solution that I'm aware of.