r2dbc Unit Test - repository doesn't return anything after saving entity - spring-webflux

I'm learning Reative jdbc with R2DBC MySQL. I have a repository like this:
public interface UserRepository extends ReactiveCrudRepository<User, Long> {
Mono<User> findByEmail(String email);
I created an unit test in order to test the repository with a memory data base usin H2. The test file looks like this:
#RunWith(SpringRunner.class)
#DataR2dbcTest
#TestPropertySource(locations = "classpath:application-test.properties")
public class UserRepositoryTest {
#Autowired
private UserRepository userRepository;
#BeforeClass
public static void initDataBase() {
ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:mem:///testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;");
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
R2dbcEntityTemplate template = new R2dbcEntityTemplate(databaseClient);
String query = "create table user (id int unsigned not null AUTO_INCREMENT, email varchar(50) not null, password varchar(100) not null, first_name varchar(50) not null, last_name varchar(50) not null, description varchar(50), phone_number varchar(50), user_image_id int unsigned, need_refresh_pass boolean not null, PRIMARY KEY (id));";
template.getDatabaseClient().execute(query).fetch().rowsUpdated().block();
}
That method creates the table because R2DBC doesn't create it automatically.
And then I have the test:
#Test
public void whenFindingAnUserReturnTheUserIfExist() {
User user = new User("email#mail.com", "pass", "name", "lastNmae", "description", "123123");
userRepository.save(user);
StepVerifier.create(userRepository.findByEmail("email#mail.com")).expectNextMatches(userCreated -> userCreated.getEmail().equals("email#mail.com")).verifyComplete();
}
When I run the test, the console shows:
java.lang.AssertionError: expectation "expectNextMatches" failed (expected: onNext(); actual: onComplete())
It seems to be that the findByEmail method doesn't return anything.
What am I doing wrong?
POM file:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<!-- For testing possibility -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<version>0.8.2.RELEASE</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-h2</artifactId>
</dependency>

I realized my mistake.
I forgot to add .subscribe() to the method userRepository.save(user);
So the test method is:
#Test
public void whenFindingAnUserReturnTheUserIfExist() {
User user = new User("email#mail.com", "pass", "name", "lastNmae", "description", "123123");
userRepository.save(user).subscribe();
StepVerifier.create(userRepository.findByEmail("email#mail.com")).expectNextMatches(userCreated -> userCreated.getEmail().equals("email#mail.com")).verifyComplete();
}

Related

UnrecognizedPropertyException in FasterXML

I read String "{"name":"John","timestamp":"2020-08-14T11:47:52.297194Z"}" when i convert it into POJO using fasterXML i get the below exception,
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "timestamp" (class com.job.model.Person), not marked as ignorable (2 known properties: "name", "timeStamp"])
My POJO is,
#Data
#NoArgsConstructor
#Table(keyspace = "keyspace", name = "testTable")
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "name")
private String name;
#Column(name = "timeStamp")
//#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC") // Tried with this no luck.
private Instant timeStamp;
}
I added the required dependency from the below url,
https://github.com/FasterXML/jackson-modules-java8, and also
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
ObjectMapper objectMapper = JsonMapper.builder()
.addModule(new ParameterNamesModule())
.addModule(new Jdk8Module())
.addModule(new JavaTimeModule())
.build();
is registered.
Json has timestamp while pojo has timeStamp. Either rename in pojo or use #JsonProperty("timestamp")
#JsonProperty("timestamp")
private Instant timeStamp;

add annotation to static method with byte buddy

I have the following code
public class InstrumentedArquillian extends BlockJUnit4ClassRunner {
static {
net.bytebuddy.agent.ByteBuddyAgent.install();
new ByteBuddy()
.redefine(BaseIT.class)
.method(named("createDeployment"))
.intercept(???)
.annotateMethod(AnnotationDescription.Builder.ofType(Deployment.class).build())
.make()
.load(InstrumentedArquillian.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()).getLoaded();
}
}
public class BaseIT {
public static WebArchive createDeployment() {
return DeploymentBuilder.war();
}
}
I would like to add the annotation Deployment, method createDeployment, class BaseIT without changing any kind of implementation
Well, later I found Add method annotation at runtime with Byte Buddy
net.bytebuddy.agent.ByteBuddyAgent.install();
Method existingMethod = BaseIT.class.getMethod("createDeployment");
AnnotationDescription annotationDescription = AnnotationDescription.Builder.ofType(Deployment.class).build();
AsmVisitorWrapper visit = new MemberAttributeExtension.ForMethod().annotateMethod(annotationDescription).on(ElementMatchers.anyOf(existingMethod));
new ByteBuddy()
.redefine(BaseIT.class)
.visit(visit)
.make()
.load(InstrumentedArquillian.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()).getLoaded();
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.10.0</version>
</dependency>

It´s possible to do Database driven tests using data tables using Karate? [duplicate]

This question already has an answer here:
How to pull data from a DB to compare with rest api response from karate
(1 answer)
Closed 1 year ago.
When writing my API tests with Cucumber I have implemented some step definitions that allow specifying the data that needs to exist in the database for each scenario.
Something like this:
Given I have database table "users" with data:
| id | name |
| 1 | User 1 |
This will do an insert in the specified table.
Is it possible to do something like this with Karate?
Thank you.
Yes it is, you will need a insertRows method in your DBUTIL file which i borrowed from #peter
you can then call the methods and pass the variable from the table
Background:
* def config = {username: 'XXXX', password: 'XXXXX', url: 'jdbc:oracle:thin:#XXXXX.net:6236/XXXX_XXXXX', driverClassName: 'oracle.jdbc.driver.OracleDriver'}
* def DbUtil = Java.type('util.DbUtils')
* def db = new DbUtil(config)
def Value = db.insertrows(INSERT INTO sales.promotions (promotion_name,discount, start_date,expired_date)VALUES(<name>);)*
below is the example of DB file, you will need to add dependencies with maven or gradle
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc6_g</artifactId>
<version>12.1.0.2</version>
</dependency>
package util;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class DbUtils {
private static final Logger logger = LoggerFactory.getLogger(DbUtils.class);
private final JdbcTemplate jdbc;
public DbUtils(Map<String, Object> config) {
String url = (String) config.get("url");
String username = (String) config.get("username");
String password = (String) config.get("password");
String driver = (String) config.get("driverClassName");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
jdbc = new JdbcTemplate(dataSource);
logger.info("init jdbc template: {}", url);
}
public Object readValue(String query) {
return jdbc.queryForObject(query, Object.class);
}
public Map<String, Object> readRow(String query) {
return jdbc.queryForMap(query);
}
public List<Map<String, Object>> readRows(String query) {
return jdbc.queryForList(query);
}
public void insertRows(final String sql){
jdbc.batchUpdate(new String[]{sql});
}
}

Custom Json Validation in anypoint studio

I am trying to validate JSon using the json schema validator. But it returns a generic message.
"Json content is not compliant with schema" .
I have a HTTP POST REQUEST which sends a payload as follows:
{ "key1" : "value1", "key2" : "value2" ,"key3": "value3" }
if key1 and key2 is missing . I want it to give error messages as follows:
{{
errorCode :1001,
errorMessage : key1 is missing",
},
errorCode :1002,
errorMessage : key2 is missing"
}
}
I tried writing the errors to a file(json file containing all the warnings and messages}
looks something like this:
{
"level" : "error",
"domain" : "validation",
"keyword" : "required",
"message" : "object has missing required properties ([\"key1\",\"key2\",\"key3\"])",
"required" : [ "key1", "key2", "key3"],
"missing" : [ "key1", "key2"]
}
This is just a small part of this file. I'll have to loop through the file to reach this information. Is there any other way , I can perform custom validations and return proper error messages to the user.
EDIT 1:
I have created the following RequestObj class:
public class RequestObj {
#Valid
#NotBlank
#NotNull
private String key1;
#Valid
#NotBlank
private String key2;
#Valid
#NotBlank
private String key3;
#Override
public String toString() {
return "RequestObj [key1=" + key1 + ", key2=" + key2 + ", key3=" + key3 + "]";
}
It is not validating key1 as not null.
postman request :
POST /validate HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"key2" :"gg",
"key3" : "hh"
}
EDIT 2:
when I implement the validator interface. I dont get access to the mule Event. How will I access the json that I need to validate in this case ?
This is how my result looks after performing custom validations on the json input.
I used JSR-303 annotations for validating the data.
class Example{
#NotBlank
#Size(min = 3, max = 5)
private String key1;
#Pattern(regexp=".+#.+\\.[a-z]+") // email
private String key2;
private String key3;
}
then I wrote a custom validator and I invoked the static function validate by passing all the values:
public class ValidationServiceImpl {
public static HashMap<String,String> validate(String key1 , String key2 , String key3) {
HashMap<String,String> result = new HashMap();
Example req = new Example(key1 , key2, key3);
Validator validator;
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator = validatorFactory.getValidator();
Set<ConstraintViolation<Example>> violations = validator.validate(req);
if(!CollectionUtils.isEmpty(violations)) {
for (ConstraintViolation<Example> violation : violations)
{
String propertyPath = violation.getPropertyPath().toString();
String message = violation.getMessage();
result.put(propertyPath, message);
}
}
return result;
}
}
The result is the hashmap which returns all the violations.Logging it will give you the result.
POM dependencies required are:
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.el/javax.el-api -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish/javax.el -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
If the built-in JSON validator doesn't provide the validation or error reporting that you need, then you have to implement your own custom validator in Java. See the docs on how to implement a custom validator by extending the Validator interface and in your implementation class you can use any Java library to validate JSON, like for example Jackson or GSON. Then you can customize the error handling.

How to call ResolveCustomer and GetEntitlements from aws-marketplace?

I find java sdk
but I can't find example of usage.
I need to call ResolveCustomer (produces a token for the product and user) and GetEntitlements (gives a list of rights for the product and the user).
Has anyone used this service?
Here is full example to get information about client from aws marketplace.
You should to use this librarys:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-marketplacemeteringservice</artifactId>
<version>1.11.192</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-marketplaceentitlement</artifactId>
<version>1.11.194</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
Java code:
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.marketplaceentitlement.AWSMarketplaceEntitlementClient;
import com.amazonaws.services.marketplaceentitlement.AWSMarketplaceEntitlementClientBuilder;
import com.amazonaws.services.marketplaceentitlement.model.GetEntitlementsRequest;
import com.amazonaws.services.marketplaceentitlement.model.GetEntitlementsResult;
import com.amazonaws.services.marketplacemetering.*;
import com.amazonaws.services.marketplacemetering.model.*;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class R
{
#Test
public void test() throws Exception
{
AWSCredentialsProvider provider = new AWSCredentialsProvider()
{
public AWSCredentials getCredentials()
{
return new AWSCredentials()
{
public String getAWSAccessKeyId()
{
return "<YOUR ACCESS KEY>";
}
public String getAWSSecretKey()
{
return "YOUR SECRET KEY";
}
};
}
public void refresh()
{
}
};
AWSMarketplaceMeteringClientBuilder b = AWSMarketplaceMeteringClient.builder();
b.setRegion("us-east-1"); // YOUR AWS REGION
b.setCredentials(provider);
AWSMarketplaceMetering c = b.build();
ResolveCustomerRequest r = new ResolveCustomerRequest();
r.setRegistrationToken(<YOUR "x-amzn-marketplace-token">); // it comes to your application in the url parameter when the user clicks the buy button in the aws market
final ResolveCustomerResult response = c.resolveCustomer(r);
AWSMarketplaceEntitlementClientBuilder entitlementClientBuilder = AWSMarketplaceEntitlementClient.builder();
entitlementClientBuilder.setRegion("us-east-1");
entitlementClientBuilder.setCredentials(provider);
GetEntitlementsRequest getEntitlementsRequest = new GetEntitlementsRequest();
getEntitlementsRequest.setProductCode(response.getProductCode());
getEntitlementsRequest.setFilter(new HashMap<String, List<String>>()
{{
put("CUSTOMER_IDENTIFIER", new ArrayList<String>()
{{
add(response.getCustomerIdentifier());
}});
}});
GetEntitlementsResult entitlementsResult = entitlementClientBuilder.build().getEntitlements(getEntitlementsRequest);
entitlementsResult = null;
}
}
Also your should add policy in your aws account: