getting error : Data provider mismatch Method: loginTest - json

Please help me to resolve this issue. I am trying to extract data from Json using data provider for one of my test case. I have done the below code.
This below method is in base class :
public List<HashMap<String, String>> getJsonDataToMap(String filePath) throws IOException {
String jsonContent = FileUtils.readFileToString(new File(filePath), StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper();
List<HashMap<String, String>> data = mapper.readValue(jsonContent, new TypeReference<List<HashMap<String, String>>>() {
});
return data;
}
Now Login.Test class is extending Base class and i have created these methods to extract the data from json and use in in test case :
public class LoginTest extends BaseClass {
public static String dataPath="src/test/java/com/automationqa/testData/LoginData.json";
#DataProvider(name = "testdatalogin")
public Object[][] getData() throws IOException {
List<HashMap<String, String>> data = getJsonDataToMap(dataPath);
return new Object[][] {{data.get(0), data.get(1)}};
}
#Test(dataProvider = "testdatalogin")
public void loginTest(HashMap<String, String> input) {
loginPage.enterUserName(input.get("userid"));
loginPage.enterPassword(input.get("password"));
loginPage.clickOnLogin();
String pageTitle = driver.getTitle();
Assertions.assertThat(pageTitle).isEqualTo("Guru99 Bank Manager HomePage");
}
JSon file :
[
{
"userid": "mngr452488",
"password": "davysav"
},
{
"userid": "mgr45248xyz",
"password": "heavyset"
}
]
but getting below error:
org.testng.internal.reflect.MethodMatcherException:
Data provider mismatch
Method: loginTest([Parameter{index=0, type=java.util.HashMap, declaredAnnotations=[]}])
Arguments: [(java.util.HashMap) {password=davysav, userid=mngr452488},(java.util.HashMap) {password=heavyset, userid=mgr45248xyz}]
at org.testng.internal.reflect.DataProviderMethodMatcher.getConformingArguments(DataProviderMethodMatcher.java:45)
at org.testng.internal.Parameters.injectParameters(Parameters.java:796)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:983)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.TestRunner.privateRun(TestRunner.java:648)
at org.testng.TestRunner.run(TestRunner.java:505)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
at org.testng.SuiteRunner.run(SuiteRunner.java:364)
JSon file :
[
{
"userid": "mngr452488",
"password": "davysav"
},
{
"userid": "mgr45248xyz",
"password": "heavyset"
}
]
but getting below error:
org.testng.internal.reflect.MethodMatcherException:
Data provider mismatch
Method: loginTest([Parameter{index=0, type=java.util.HashMap, declaredAnnotations=[]}])
Arguments: [(java.util.HashMap) {password=davysav, userid=mngr452488},(java.util.HashMap) {password=heavyset, userid=mgr45248xyz}]
at org.testng.internal.reflect.DataProviderMethodMatcher.getConformingArguments(DataProviderMethodMatcher.java:45)
at org.testng.internal.Parameters.injectParameters(Parameters.java:796)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:983)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.TestRunner.privateRun(TestRunner.java:648)
at org.testng.TestRunner.run(TestRunner.java:505)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
at org.testng.SuiteRunner.run(SuiteRunner.java:364)

Your provider provides two arguments for each iteration but test method takes only one.
I think you want to do something like
#DataProvider(name = "testdatalogin")
public Object[][] getData() throws IOException {
List<Map<String, String>> data = getJsonDataToMap(dataPath);
return new Object[][] {{data.get(0)}, {data.get(1)}};
}

Related

json to collection (list) in SpringBoot

I'm trying to get a list of orders from another service(url) with #GetMapping.
I can't get the json objects and convert them to a list.I keep getting these and similar errors:
org.springframework.web.client.HttpServerErrorException$InternalServerError:
500 Server Error: [java.lang.IllegalStateException: Not a JSON Object: null at com.google.gson.JsonElement.getAsJsonObject(JsonElement.java:91)
What should I do? please help me for how many days i can't find the right solution.
#Autowired
private final RestTemplate restTemplate;
#Value("${baseUrl}")
private String baseUrl;
public OrdersController(OrdersService ordersService, TradesService tradesService, RestTemplate restTemplate) {
this.ordersService = ordersService;
this.tradesService = tradesService;
this.restTemplate = restTemplate;
}
#GetMapping (value ="/restDeneme", produces="application/json")
public List <Orders> getOrders(){
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<Orders>> response = restTemplate.exchange(
baseUrl , HttpMethod.GET,entity,
new ParameterizedTypeReference<List<Orders>>() {});
return response.getBody();
}
You should try to receive the data as a JSON object
for a JSON format like this;
{
"Kml": {
"bicak": "AWAKEN YOUR SENSES",
"jobsearch": "JOB SEARCH",
"contact": "CONTACT",
"video": "ENCHANTING BEACHSCAPES",
"createprofile": "CREATE PROFILE"
}
}
You can call it like this;
String loudScreaming = json.getJSONObject("Kml").getString("bicak");

How to configure kafka deserializer so that it let pass only keys with values?

I have a kafka consumer which does the deserialization of JSON.
I get big messages like :
{
data1: [],
data2: ["content"],
data3: null,
data4: [],
data5: "foo",
data6: "",
data7: [""],
data8: [null],
...
dataX: []
}
with a lot of keys, where the values are null respective empty lists. I want handle only the keys, which does have values or lists with senseful content like data2 or data5 and ignore the others. Even with data6 (empty string) and data7 (list with empty string) I want stay. This shall pass.
I have this kafka consumer configuration.
private void configureAndInitConsumer() {
final Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroupId);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, autoCommit);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, org.apache.kafka.connect.json.JsonDeserializer.class.getName());
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords);
consumer = new KafkaConsumer<>(props);
}
I see, that here the org.apache.kafka.connect.json.JsonDeserializer is configured. But the config is for kafka consumer.
I can configure the deserializer by replacing the KafkaConsumer constructor.
JsonDeserializer<JsonNode> valueDeserializer = createCustomizedJsonDeserializer();
consumer = new KafkaConsumer<>(props, new StringDeserializer(), valueDeserializer);
and then I add the method
private JsonDeserializer<JsonNode> createCustomizedJsonDeserializer() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, false);
return new JsonDeserializer<>(JsonNode.class, objectMapper);
}
The hint for this I got from https://github.com/spring-projects/spring-kafka/issues/915
Is is possible that the Deserializer ignores the keys without values? (empty lists or null values)
I realized that the Deserializer intern has an object mapper.
So I testest this:
public class ObjectMapperTest {
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
System.exit(new ObjectMapperTest().start());
}
private int start() throws JsonMappingException, JsonProcessingException {
String testJson = "{\"date1\":[],\"date2\":null,\"date3\":[null],\"date4\":[\"\"],\"date5\":[],\"date6\":\"\",\"date8\":\"foobar\"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
JsonNode jn = objectMapper.readTree(testJson);
System.out.println(jn);
return 0;
}
}
I get this result:
{"date1":[],"date2":null,"date3":[null],"date4":[""],"date5":[],"date6":"","date8":"foobar"}
I see there, that date2 is still there.

GraphQL java send custom error in json format

I am working in an graphql application where I have to send custom error object / message in json irrespective of whether it occurs in servlet or service.
Expected error response
{ errorCode: 400 //error goes here,
errorMessage: "my error mesage"}
It will be helpful if someone could guide me to achieve the above requirement.
GraphQL specification defines a clear format for the error entry in the response.
According to the spec, it should like this (assuming JSON format is used):
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ]
"extensions": {/* You can place data in any format here */}
}
]
So you won't find a GraphQL implementation that allows you to extend it and return some like this in the GraphQL execution result, for example:
"errors": [
{
"errorMessage": "Name for character with ID 1002 could not be fetched.",
"errorCode": 404
}
]
However, the spec lets you add data in whatever format in the extension entry. So you could create a custom Exception on the server side and end up with a response that looks like this in JSON:
"errors": [
{
"message": "Name for character with ID 1002 could not be fetched.",
"locations": [ { "line": 6, "column": 7 } ],
"path": [ "hero", "heroFriends", 1, "name" ]
"extensions": {
"errorMessage": "Name for character with ID 1002 could not be fetched.",
"errorCode": 404
}
}
]
It's quite easy to implement this on GraphQL Java, as described in the docs. You can create a custom exception that overrides the getExtensions method and create a map inside the implementation that will then be used to build the content of extensions:
public class CustomException extends RuntimeException implements GraphQLError {
private final int errorCode;
public CustomException(int errorCode, String errorMessage) {
super(errorMessage);
this.errorCode = errorCode;
}
#Override
public Map<String, Object> getExtensions() {
Map<String, Object> customAttributes = new LinkedHashMap<>();
customAttributes.put("errorCode", this.errorCode);
customAttributes.put("errorMessage", this.getMessage());
return customAttributes;
}
#Override
public List<SourceLocation> getLocations() {
return null;
}
#Override
public ErrorType getErrorType() {
return null;
}
}
then you can throw the exception passing in the code and message from inside your data fetchers:
throw new CustomException(400, "A custom error message");
Now, there is another way to tackle this.
Assuming you are working on a Web application, you can return errors (and data, for that matter) in whatever format that you want. Although that is a bit awkward in my opinion. GraphQL clients, like Apollo, adhere to the spec, so why would you want to return a response on any other format? But anyway, there are lots of different requirements out there.
Once you get a hold of an ExecutionResult, you can create a map or object in whatever format you want, serialise that as JSON and return this over HTTP.
Map<String, Object> result = new HashMap<>();
result.put("data", executionResult.getData());
List<Map<String, Object>> errors = executionResult.getErrors()
.stream()
.map(error -> {
Map<String, Object> errorMap = new HashMap<>();
errorMap.put("errorMessage", error.getMessage());
errorMap.put("errorCode", 404); // get the code somehow from the error object
return errorMap;
})
.collect(toList());
result.put("errors", errors);
// Serialize "result" and return that.
But again, having a response that doesn't comply with the spec doesn't make sense in most of the cases.
The other posted answer didn't work for me.
I found a solution by creating the following classes:
1) A throwable CustomException of GraphQLError type (just like mentioned in another answer).
2) Creating a GraphQLError Adaptor, which is not a Throwable.
3) A custom GraphQLErrorHandler to filter the custom exception.
Step 1:
The below throwable CustomGraphQLException implements GraphQLError because the GraphQLErrorHandler interface accepts errors only of type GraphQLError.
public class CustomGraphQLException extends RuntimeException implements GraphQLError {
private final int errorCode;
private final String errorMessage;
public CustomGraphQLException(int errorCode, String errorMessage) {
super(errorMessage);
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
#Override
public List<SourceLocation> getLocations() {
return null;
}
#Override
public ErrorType getErrorType() {
return null;
}
#Override
public String getMessage() {
return this.errorMessage;
}
#Override
public Map<String, Object> getExtensions() {
Map<String, Object> customAttributes = new HashMap<>();
customAttributes.put("errorCode", this.errorCode);
customAttributes.put("errorMessage", this.getMessage());
return customAttributes;
}
}
Step 2:
A non-throwable adaptor of GraphQLError is created to avoid the stack-trace of the above custom exception being passed in the final GraphQL Error Response.
public class GraphQLErrorAdaptor implements GraphQLError {
private final GraphQLError graphQLError;
public GraphQLErrorAdaptor(GraphQLError graphQLError) {
this.graphQLError = graphQLError;
}
#Override
public List<SourceLocation> getLocations() {
return graphQLError.getLocations();
}
#Override
public ErrorType getErrorType() {
return graphQLError.getErrorType();
}
#Override
public String getMessage() {
return graphQLError.getMessage();
}
#Override
public Map<String, Object> getExtensions() {
return graphQLError.getExtensions();
}
}
Step 3:
A custom GraphQLErrorHandler is implemented to filter the custom CustomGraphQLException and avoid its replacement with the default graphQL error response.
public class CustomGraphQLErrorHandler implements GraphQLErrorHandler {
public CustomGraphQLErrorHandler() { }
public List<GraphQLError> processErrors(List<GraphQLError> errors) {
List<GraphQLError> clientErrors = this.filterGraphQLErrors(errors);
List<GraphQLError> internalErrors = errors.stream()
.filter(e -> isInternalError(e))
.map(GraphQLErrorAdaptor::new)
.collect(Collectors.toList());
if (clientErrors.size() + internalErrors.size() < errors.size()) {
clientErrors.add(new GenericGraphQLError("Internal Server Error(s) while executing query"));
errors.stream().filter((error) -> !this.isClientError(error)
).forEach((error) -> {
if (error instanceof Throwable) {
LOG.error("Error executing query!", (Throwable) error);
} else {
LOG.error("Error executing query ({}): {}", error.getClass().getSimpleName(), error.getMessage());
}
});
}
List<GraphQLError> finalErrors = new ArrayList<>();
finalErrors.addAll(clientErrors);
finalErrors.addAll(internalErrors);
return finalErrors;
}
protected List<GraphQLError> filterGraphQLErrors(List<GraphQLError> errors) {
return errors.stream().filter(this::isClientError).collect(Collectors.toList());
}
protected boolean isClientError(GraphQLError error) {
return !(error instanceof ExceptionWhileDataFetching) && !(error instanceof Throwable);
}
protected boolean isInternalError(GraphQLError error) {
return (error instanceof ExceptionWhileDataFetching) &&
(((ExceptionWhileDataFetching) error).getException() instanceof CustomGraphQLException);
}
}
Step 4:
Configure the CustomGraphQLErrorHandler in GraphQLServlet. I am assuming you are using spring-boot for this step.
#Configuration
public class GraphQLConfig {
#Bean
public ServletRegistrationBean graphQLServletRegistrationBean(
QueryResolver queryResolver,
CustomGraphQLErrorHandler customGraphQLErrorHandler) throws Exception {
GraphQLSchema schema = SchemaParser.newParser()
.schemaString(IOUtils.resourceToString("/library.graphqls", Charset.forName("UTF-8")))
.resolvers(queryResolver)
.build()
.makeExecutableSchema();
return new ServletRegistrationBean(new SimpleGraphQLServlet(schema,
new DefaultExecutionStrategyProvider(), null, null, null,
customGraphQLErrorHandler, new DefaultGraphQLContextBuilder(), null,
null), "/graphql");
}
}
Reference

.NET Core Configuration Serialization

Is there a way to serialize an object so that it could then be rehydrated by .Net Core Configuration Binder?
Basically, I'd like to get this Test to pass:
[Test]
public void Can_Serialize_And_Rehydrate()
{
var foo = new Foo{ Prop1 = 42; Prop2 = "Test" }
Dictionary<string, string> serialized = Serialize(Foo);
var deserializedFoo = new Foo();
new ConfigurationBuilder()
.AddInMemoryCollection(serialized)
.Build()
.Bind(deserializedFoo);
Assert.AreEqual(deserializedFoo.Prop1, 42);
Assert.AreEqual(deserializedFoo.Prop2, "Test");
}
Is there a Serializer out-of-the-box, or am I'm going to need to write my own Serialize() method?
AddInMemoryCollection's signature is like below, so why are you trying to serialize your dictionary here? You could just use it as it is.
public static IConfigurationBuilder AddInMemoryCollection(
this IConfigurationBuilder configurationBuilder,
IEnumerable<KeyValuePair<string, string>> initialData)
If you like to know more about how to test your custom configurations, I would suggest to look here:
https://github.com/aspnet/Configuration/blob/1.0.0/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationBinderTests.cs
I was able to get this working by "hijacking" a JsonConfigurationProvider and plugging serialized Json directly into it. Not sure if this is the best way, but it does work:
public class ConfigurationSerializer
{
private class CustomJsonProvider : JsonConfigurationProvider
{
public CustomJsonProvider() : base(new JsonConfigurationSource())
{
}
public IDictionary<string, string> GetData(Stream s)
{
Load(s);
// Return the Configuration Dictionary
return Data;
}
}
public Dictionary<string, string> Serialize(object o)
{
var serialized =
JsonConvert.SerializeObject(
o,
new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
{
var jsonProvider = new CustomJsonProvider();
return jsonProvider
.GetData(ms)
.ToDictionary(key => key.Key, value => value.Value);
}
}
}

Array retrieval from JSON file

I have an array in JSON file which look like this
{ "fields": [
{
"name": "order_id",
"type": "INTEGER",
"position": 0
},
{
"name": "district_id",
"type": "INTEGER",
"position": 1
}]
}
I'm using a TREE MODEL in retrieving the contents of the array "fields" and my code looks like this ..
public static void main(String[] args) throws JsonParseException, IOException {
File jsonFile = new File("metadata.json");
String theJsonString = jsonFile.toString();
String name = null;
String type =null;
int position = 0;
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
JsonNode rootNode = mapper.readTree(theJsonString);
JsonNode fields = rootNode.get("fields");
if (fields != null) {
for (int i = 0; i < fields.size(); i ++) {
if(fields.has("name"))
name = fields.get("name").getTextValue();
if(fields.has("type"))
type = fields.get("type").getTextValue();
if(fields.has("position"))
position = fields.get("position").getIntValue();
System.out.println(name);
}
}
}
I get the following error during the run time ::
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('/' (code 47)): maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)
at [Source: java.io.StringReader#3eed2cab; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1432)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:385)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:306)
at org.codehaus.jackson.impl.ReaderBasedParser._skipComment(ReaderBasedParser.java:1498)
at org.codehaus.jackson.impl.ReaderBasedParser._skipWSOrEnd(ReaderBasedParser.java:1474)
at org.codehaus.jackson.impl.ReaderBasedParser.nextToken(ReaderBasedParser.java:362)
at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2761)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2709)
at org.codehaus.jackson.map.ObjectMapper.readTree(ObjectMapper.java:1533)
at metadata.JSONParser.main(JSONParser.java:32)
I have just started working with JSON and hence unable to find a solution. Could anybody help me resolve this?
If you want the contents of the file metadata.json then calling toString on the file will not give you that. Instead it will give you a string which holds the path to the filename.
Instead create a FileInputStream from the File like so:
FileInputStream fis = new FileInputStream(jsonFile);
The you can use it with the mapper
JsonNode rootNode = mapper.readTree(fis);
You might also want to call fields.get(i) when you are iterating through the array to access each JsonNode contained in the array.
I have the same problem and I fixed the problem finally by this code to get the JsonParser object.
FileInputStream fis = new FileInputStream(path);
JsonParser jp = new JsonFactory().createParser(fis);
I had the same problem few days ago. My JSON have the next syntax:
{ "boxes": [
{
"name": "redBox.png",
"version": 15
},
{
"name": "blueBox.png",
"version": 9
}
]
}
I had to create method which return me POJO classes with box versions. My solution is follow:
private static List<DataVersion> receiveDataVersions() throws IOException
{
String path = System.getProperty( "user.dir" ) + File.separator +
"versions.json";
List<DataVersion> versions = new ArrayList<>();
JsonNode folder = null;
try( InputStream stream = new FileInputStream( path ) )
{
folder = new ObjectMapper().readTree( stream );
}
JsonNode boxes = folder.get( "inst" );
boxes.forEach( version -> versions.add( new DataVersion(
version.get( "name" ).getTextValue(),
version.get( "version" ).getIntValue() ) ) );
return versions;
}
POJO is as follows:
public class DataVersion
{
private String name;
private int version;
public DataVersion() {
}
public DataVersion(String name, int version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVersion() {
return version;
}
public void setVersion(int version){
this.version=version;
}
#Override
public String toString()
{
return "DataVersion [" + "name='" + name + '\'' + ", version=" +
version + ']';
}
}
try this in your code
jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);