How to test controller action in Grails 3.3.6 without using services - testing

I have created Grails Application with one domain and controller. In development environment i have inserted two entry for domain.I want to perform integration testing such that it fetch records from the database and return the total size.Below is my source code which i tried.
Below is my domain
Student.groovy.
import grails.gorm.transactions.Transactional
#Transactional
class Student {
String name
String rollnumber
static constraints = {
}
}
Below is my controller:-
import grails.gorm.transactions.Transactional
#Transactional
class StudentController {
def readall(){
println "inside read all "+Student.getAll().size()
respond Student.getAll()
}
}
Below is my Integration Testing code:
import grails.testing.gorm.DomainUnitTest
import grails.testing.mixin.integration.Integration
import grails.testing.web.controllers.ControllerUnitTest
import grails.validation.ValidationException
import spock.lang.Specification
#Integration
class StudentControllerSpec extends Specification implements ControllerUnitTest<StudentController>, DomainUnitTest<Student> {
void "getAllStudentList"(){
given:
def studentList=[]
when:
request.method = 'GET'
controller.readall()
println studentList.size()
then:
studentList.size()==1
}
}
Below is my application.yml file
---
hibernate:
cache:
queries: false
use_second_level_cache: false
use_query_cache: false
dataSource:
pooled: true
jmxExport: true
driverClassName: org.h2.Driver
username: sa
password: ''
environments:
development:
dataSource:
dbCreate: create-drop
url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
test:
dataSource:
dbCreate: update
url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
production:
dataSource:
dbCreate: none
url: jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED
i'm getting below exception while running test case
Configuring Spring Security Core ...
... finished configuring Spring Security Core
2019-04-21 16:05:07.979 ERROR --- [ Test worker] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'methodValidationPostProcessor' defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]: Unsatisfied dependency expressed through method 'methodValidationPostProcessor' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastoreServiceRegistry': Cannot resolve reference to bean 'hibernateDatastore' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.MappingException: Could not determine type for: org.springframework.transaction.PlatformTransactionManager, at table: student, for columns: [org.hibernate.mapping.Column(transaction_manager)]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1181)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1075)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:225)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:703)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:528)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)

Remove #Transactional from your domain class. #Transactional are used to begin transactions on services/controllers - but it does not make sense in a domain class.
The error is GORM is trying to create a column of transaction_manager because #Transactional adds a property of transactionManger to the class and is of a type that doesn't make sense to hibernate.

Related

Ktor-server-test-host did not cleaned up Exposed database instannce across tests

I'm working on a web service using Ktor 1.6.8 and Exposed 0.39.2.
My application module and database is setup as following:
fun Application.module(testing: Boolean = false) {
val hikariConfig =
HikariConfig().apply {
driverClassName = "org.postgresql.Driver"
jdbcUrl = environment.config.propertyOrNull("ktor.database.url")?.getString()
username = environment.config.propertyOrNull("ktor.database.username")?.getString()
password = environment.config.propertyOrNull("ktor.database.password")?.getString()
maximumPoolSize = 10
isAutoCommit = false
transactionIsolation = "TRANSACTION_REPEATABLE_READ"
validate()
}
val pool = HikariDataSource(hikariConfig)
val db = Database.connect(pool, {}, DatabaseConfig { useNestedTransactions = true })
}
I use ktor-server-test-host, Test Containers and junit 5 to test the service. My test looks similar like below:
#Testcontainers
class SampleApplicationTest{
companion object {
#Container
val postgreSQLContainer = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13.4-alpine")).apply {
withDatabaseName("database_test")
}
}
#Test
internal fun `should make request successfully`() {
withTestApplication({
(environment.config as MapApplicationConfig).apply {
put("ktor.database.url", postgreSQLContainer.jdbcUrl)
put("ktor.database.user", postgreSQLContainer.username)
put("ktor.database.password", postgreSQLContainer.password)
}
module(testing = true)
}) {
handleRequest(...)
}
}
}
I observed an issue that if I ran multiple test classes together, some requests ended up using old Exposed db instance that was setup in a previous test class, causing the test case failed because the underlying database was already stopped.
When I ran one test class at a time, all were running fine.
Please refer to the log below for the error stack trace:
2022-10-01 08:00:36.102 [DefaultDispatcher-worker-5 #request#103] WARN Exposed - Transaction attempt #1 failed: java.sql.SQLTransientConnectionException: HikariPool-4 - Connection is not available, request timed out after 30001ms.. Statement(s): INSERT INTO cards (...)
org.jetbrains.exposed.exceptions.ExposedSQLException: java.sql.SQLTransientConnectionException: HikariPool-4 - Connection is not available, request timed out after 30001ms.
at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:49)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:143)
at org.jetbrains.exposed.sql.Transaction.exec(Transaction.kt:128)
at org.jetbrains.exposed.sql.statements.Statement.execute(Statement.kt:28)
at org.jetbrains.exposed.sql.QueriesKt.insert(Queries.kt:73)
at com.example.application.services.CardService$createCard$row$1.invokeSuspend(CardService.kt:53)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt$suspendedTransactionAsyncInternal$1.invokeSuspend(Suspended.kt:127)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Caused by: java.sql.SQLTransientConnectionException: HikariPool-4 - Connection is not available, request timed out after 30001ms.
at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:695)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:197)
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
at org.jetbrains.exposed.sql.Database$Companion$connect$3.invoke(Database.kt:142)
at org.jetbrains.exposed.sql.Database$Companion$connect$3.invoke(Database.kt:139)
at org.jetbrains.exposed.sql.Database$Companion$doConnect$3.invoke(Database.kt:127)
at org.jetbrains.exposed.sql.Database$Companion$doConnect$3.invoke(Database.kt:128)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:69)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction$connectionLazy$1.invoke(ThreadLocalTransactionManager.kt:68)
at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager$ThreadLocalTransaction.getConnection(ThreadLocalTransactionManager.kt:75)
at org.jetbrains.exposed.sql.Transaction.getConnection(Transaction.kt)
at org.jetbrains.exposed.sql.statements.InsertStatement.prepared(InsertStatement.kt:157)
at org.jetbrains.exposed.sql.statements.Statement.executeIn$exposed_core(Statement.kt:47)
... 19 common frames omitted
Caused by: org.postgresql.util.PSQLException: Connection to localhost:49544 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:303)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:223)
at org.postgresql.Driver.makeConnection(Driver.java:465)
at org.postgresql.Driver.connect(Driver.java:264)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:725)
at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:711)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
I tried to add some cleanup code for Exposed's TransactionManager in my application module as following:
fun Application.module(testing: Boolean = false) {
// ...
val db = Database.connect(pool, {}, DatabaseConfig { useNestedTransactions = true })
if (testing) {
environment.monitor.subscribe(ApplicationStopped) {
TransactionManager.closeAndUnregister(db)
}
}
}
However, the issue still happened, and I also observed additional error as following:
2022-10-01 08:00:36.109 [DefaultDispatcher-worker-5 #request#93] ERROR Application - Unexpected error
java.lang.RuntimeException: database org.jetbrains.exposed.sql.Database#3bf4644c don't have any transaction manager
at org.jetbrains.exposed.sql.transactions.TransactionApiKt.getTransactionManager(TransactionApi.kt:149)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt.closeAsync(Suspended.kt:85)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt.access$closeAsync(Suspended.kt:1)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt$suspendedTransactionAsyncInternal$1.invokeSuspend(Suspended.kt:138)
(Coroutine boundary)
at org.mpierce.ktor.newrelic.KtorNewRelicKt$runPipelineInTransaction$2.invokeSuspend(KtorNewRelic.kt:178)
at org.mpierce.ktor.newrelic.KtorNewRelicKt$setUpNewRelic$2.invokeSuspend(KtorNewRelic.kt:104)
at io.ktor.routing.Routing.executeResult(Routing.kt:154)
at io.ktor.routing.Routing$Feature$install$1.invokeSuspend(Routing.kt:107)
at io.ktor.features.ContentNegotiation$Feature$install$1.invokeSuspend(ContentNegotiation.kt:145)
at io.ktor.features.StatusPages$interceptCall$2.invokeSuspend(StatusPages.kt:102)
at io.ktor.features.StatusPages.interceptCall(StatusPages.kt:101)
at io.ktor.features.StatusPages$Feature$install$2.invokeSuspend(StatusPages.kt:142)
at io.ktor.features.CallLogging$Feature$install$2.invokeSuspend(CallLogging.kt:188)
at io.ktor.server.testing.TestApplicationEngine$callInterceptor$1.invokeSuspend(TestApplicationEngine.kt:296)
at io.ktor.server.testing.TestApplicationEngine$2.invokeSuspend(TestApplicationEngine.kt:50)
Caused by: java.lang.RuntimeException: database org.jetbrains.exposed.sql.Database#3bf4644c don't have any transaction manager
at org.jetbrains.exposed.sql.transactions.TransactionApiKt.getTransactionManager(TransactionApi.kt:149)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt.closeAsync(Suspended.kt:85)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt.access$closeAsync(Suspended.kt:1)
at org.jetbrains.exposed.sql.transactions.experimental.SuspendedKt$suspendedTransactionAsyncInternal$1.invokeSuspend(Suspended.kt:138)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Could someone show me what could be the issue here with my application code & test setup?
Thanks and regards.

Sylius\Component\Core\Model\Product::getMainTaxon() returns proxy insead of Taxoninterface

getMainTaxon() returns Proxy instead of TaxonInterface
I am doing migration from sylius 1.1 to sylius 1.5. Everything works fine except this error. I have no idea what should i do with this error.
My _sylius.yaml contains these entries:
sylius_product:
resources:
product:
classes:
repository: App\Repository\ProductRepository
model: App\Entity\Product
controller: App\Controller\ProductController
translation:
classes:
model: App\Entity\ProductTranslation
sylius_taxonomy:
resources:
taxon:
classes:
repository: App\Repository\TaxonRepository
model: App\Entity\Taxon
My doctrine.yaml looks like this:
doctrine:
dbal:
driver: 'pdo_mysql'
server_version: '5.7'
charset: UTF8
url: '%env(resolve:DATABASE_URL)%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
auto_mapping: true
mappings:
App:
is_bundle: false
type: yml
dir: '%kernel.project_dir%/config/doctrine'
prefix: 'App\Entity'
alias: App
Full error looks like this
Return value of Sylius\Component\Core\Model\Product::getMainTaxon() must be an instance of Sylius\Component\Core\Model\TaxonInterface or null, instance of Proxies__CG__\App\Entity\Taxon returned
Do you know what can cause this error and how to manage it?
finally I managed to solve this issue. Maybe it will help someone who migrates an application from legacy sylius.
In the past, I extended the Taxon entity and my Taxon.php looked like this
use Sylius\Component\Taxonomy\Model\Taxon as BaseTaxon;
class Taxon extends BaseTaxon {
The issue was I should have extended Sylius\Component\Core\Model\Taxon class so my entity file now looks like this
use Sylius\Component\Core\Model\Taxon as BaseTaxon;
class Taxon extends BaseTaxon {

Karate: How to test multipart form-data endpoint? [duplicate]

This question already has an answer here:
How to upload CSV file as a post request in Karate 0.9.0 version?
(1 answer)
Closed 2 years ago.
I have an file upload endpoint (/document) in a controller defined as follows:
#RestController
public class FileUploadController {
#Autowired
private PersonCSVReaderService personCSVReaderService;
#PostMapping(value = "/document", consumes= {MediaType.MULTIPART_FORM_DATA_VALUE})
public void handleFileUpload3(#RequestPart("file") MultipartFile file, #RequestPart("metadata") DocumentMetadata metadata) {
System.out.println(String.format("uploading file %s of %s bytes", file.getOriginalFilename(), file.getSize()));
personCSVReaderService.readPersonCSV(file, metadata);
}
}
I can test this endpoint using Advanced Rest Client (ARC) or Postman by defining the "file" part referencing the people.csv file and a text part specifying some sample metadata JSON.
Everything works fine and I get a 200 status back with the people.csv file contents being written to the console output by the service method:
uploading file people.csv of 256 bytes
{Address=1, City=2, Date of Birth=6, Name=0, Phone Number=5, State=3, Zipcode=4}
Person{name='John Brown', address='123 Main St.', city='Scottsdale', state='AZ', zipcode='85259', phoneNumber='555-1212', dateOfBirth='1965-01-01'}
Person{name='Jan Black', address='456 University Dr.', city='Atlanta', state='GA', zipcode='30306', phoneNumber='800-1111', dateOfBirth='1971-02-02'}
Person{name='Mary White', address='789 Possum Rd.', city='Nashville', state='TN', zipcode='37204', phoneNumber='888-2222', dateOfBirth='1980-03-03'}
Now, I want to run this as an automated Karate test. I have specified a MockConfig :
#Configuration
#EnableAutoConfiguration
#PropertySource("classpath:application.properties")
public class MockConfig {
// Services ...
#Bean
public PersonCSVReaderService personCSVReaderService() {
return new PersonCSVReaderService();
}
// Controllers ...
#Bean
public FileUploadController fileUploadController() {
return new FileUploadController();
}
}
I also have a MockSpringMvcServlet in the classpath and my karate-config.js is :
function fn() {
var env = karate.env; // get system property 'karate.env'
if (!env) {
env = 'dev';
}
karate.log('karate.env system property was:', env);
var config = {
env: env,
myVarName: 'someValue',
baseUrl: 'http://localhost:8080'
}
if (env == 'dev') {
var Factory = Java.type('MockSpringMvcServlet');
karate.configure('httpClientInstance', Factory.getMock());
//var result = karate.callSingle('classpath:demo/headers/common-noheaders.feature', config);
} else if (env == 'stg') {
// customize
} else if (env == 'prod') {
// customize
}
return config;
}
Other karate tests run ok using the mock servlet.
However, when I try this test to test the /document endpoint:
Feature: file upload end-point
Background:
* url baseUrl
* configure lowerCaseResponseHeaders = true
Scenario: upload file
Given path '/document'
And header Content-Type = 'multipart/form-data'
And multipart file file = { read: 'people.csv', filename: 'people.csv', contentType: 'text/csv' }
And multipart field metadata = { name: "joe", description: "stuff" }
When method post
Then status 200
I get this error:
16:14:42.674 [main] INFO com.intuit.karate - karate.env system property was: dev
16:14:42.718 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring DispatcherServlet ''
16:14:42.719 [main] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet ''
16:14:43.668 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$a4c7d08f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:14:43.910 [main] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.0.14.Final
16:14:44.483 [main] INFO o.s.s.c.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
16:14:44.968 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 2 endpoint(s) beneath base path '/actuator'
16:14:45.006 [main] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 2287 ms
16:14:45.066 [main] INFO c.i.k.mock.servlet.MockHttpClient - making mock http client request: POST - http://localhost:8080/document
16:14:45.085 [main] DEBUG c.i.k.mock.servlet.MockHttpClient -
1 > POST http://localhost:8080/document
1 > Content-Type: multipart/form-data
16:14:45.095 [main] ERROR com.intuit.karate - http request failed: null
file-upload.feature:13 - null
HTML report: (paste into browser to view) | Karate version: 0.9.2
I can only assume that the arguments did not conform to what my endpoint was expecting - I never entered the endpoint in debug mode.
I tried this:
And multipart file file = read('people.csv')
And multipart field metadata = { name: "joe", description: "stuff" }
But that was a non-starter as well.
What am I doing wrong? The people.csv is in the same folder as fileupload.feature, so I am assuming it is finding the file. I also looked at upload.feature file in the Karate demo project given here:
Karate demo project upload.feature
But I could not make it work. Any help appreciated. Thanks in advance.
The Postman request looks like this:
EDIT UPDATE:
I could not get the suggested answer to work.
Here is the feature file:
Feature: file upload
Background:
* url baseUrl
* configure lowerCaseResponseHeaders = true
Scenario: upload file
Given path '/document'
And header Content-Type = 'multipart/form-data'
* def temp = karate.readAsString('people.csv')
* print temp
And multipart file file = { value: '#(temp)', filename: 'people.csv', contentType: 'text/csv' }
And multipart field metadata = { value: {name: 'joe', description: 'stuff'}, contentType: 'application/json' }
When method post
Then status 200
And here is the console output from running that test:
09:27:22.051 [main] INFO com.intuit.karate - found scenario at line: 7 - ^upload file$
09:27:22.156 [main] INFO com.intuit.karate - karate.env system property was: dev
09:27:22.190 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring DispatcherServlet ''
09:27:22.190 [main] INFO o.s.web.servlet.DispatcherServlet - Initializing Servlet ''
09:27:23.084 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$a4c7d08f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
09:27:23.327 [main] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.0.14.Final
09:27:23.896 [main] INFO o.s.s.c.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
09:27:24.381 [main] INFO o.s.b.a.e.web.EndpointLinksResolver - Exposing 2 endpoint(s) beneath base path '/actuator'
09:27:24.418 [main] INFO o.s.web.servlet.DispatcherServlet - Completed initialization in 2228 ms
09:27:24.435 [main] INFO com.intuit.karate - [print] Name,Address,City,State,Zipcode,Phone Number,Date of Birth
John Brown,123 Main St.,Scottsdale,AZ,85259,555-1212,1965-01-01
Jan Black,456 University Dr.,Atlanta,GA,30306,800-1111,1971-02-02
Mary White,789 Possum Rd.,Nashville,TN,37204,888-2222,1980-03-03
09:27:24.482 [main] INFO c.i.k.mock.servlet.MockHttpClient - making mock http client request: POST - http://localhost:8080/document
09:27:24.500 [main] DEBUG c.i.k.mock.servlet.MockHttpClient -
1 > POST http://localhost:8080/document
1 > Content-Type: multipart/form-data
09:27:24.510 [main] ERROR com.intuit.karate - http request failed: null
file-upload.feature:14 - null
HTML report: (paste into browser to view) | Karate version: 0.9.2
Note: people.csv file reads successfully and prints in console.
Refer to this part of the docs: https://github.com/intuit/karate#read-file-as-string
So make this change:
* def temp = karate.readAsString('people.csv')
And multipart file file = { value: '#(temp)', filename: 'people.csv', contentType: 'text/csv' }
EDIT: my bad, also refer: https://github.com/intuit/karate#multipart-file
Feature: upload csv
Background: And def admin = read('classpath:com/project/data/adminLogin.json')
Scenario:
Given url baseUrl
And header Authorization = admin.token
And multipart file residentDetails = { read:'classpath:com/project/data/ResidentApp_Details.csv', filename: 'ResidentApp_Details.csv' }
When method POST
Then status 200
Note: Add only one extra line i.e And multipart file residentDetails = { read:'classpath:com/project/data/ResidentApp_Details.csv', filename: 'ResidentApp_Details.csv' }

RESTEASY003145: Unable to find a MessageBodyReader of content-type text/xml;charset=UTF-8

I'm a newbie in a REST services, but all solutions I found was due to lack of necessary providers.
Dependencies:
compile group: 'org.jboss.resteasy', name: 'resteasy-client', version: '3.6.1.Final'
compile group: 'org.jboss.resteasy', name: 'resteasy-jackson2-provider', version: '3.6.1.Final'
compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.+"
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.+"
Data class:
#JacksonXmlRootElement(localName = "Response")
data class ResponseSessionInit(#JacksonXmlProperty(localName = "Error") val error: Error)
data class Error(#JacksonXmlProperty(localName = "Text", isAttribute = true) val text: String)
Proxy:
interface L3Client {
#POST
#Consumes("text/xml;charset=UTF-8")
#Produces("text/xml; charset=UTF-8")
fun test(string: String): ResponseSessionInit
}
Proxy method invocation:
val proxy = client.target(API).proxyBuilder(L3Client::class.java).build()
println(proxy.test("<Request><ProtocolInfoGet/></Request>"))
I receive exception:
javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type text/xml;charset=UTF-8 and type class ru.abinet.commons.cft.L3.messages.ResponseSessionInit
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:156)
at org.jboss.resteasy.client.jaxrs.internal.proxy.extractors.BodyEntityExtractor.extractEntity(BodyEntityExtractor.java:60)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:150)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
at com.sun.proxy.$Proxy19.test(Unknown Source)
It really looks like if Resteasy client can't find a decoder for my XML, however I have it in path.
I can change test() method to return String and successfully parse XML with something like
val mapper = XmlMapper()
mapper.registerModule(KotlinModule())
val value = mapper.readValue(xml, ResponseSessionInit::class.java)
However, I'd like to do it automagically. What I'm missing ?
Reasteasy can't handle application/xml content-type out of the box with jackson-xml. So the idea is to write it by yourself.
#Provider
#Consumes(MediaType.TEXT_XML, MediaType.APPLICATION_XML)
class BodyReaderProvider : MessageBodyReader<Any> {
//jackson instantiation and some check code here
}
and register it
val client = ResteasyClientBuilder.newBuilder()
.register(BodyReaderProvider())

Angular 2 testing - process.env

I try to mock requests in my application, but there is a problem with process variable. I store in process.env.backendUrl url to backend API. And then in RestService I have:
constructor(private http: Http) {
this.rest = process.env.backendUrl + "/api/";
}
And now it is impossible to run tests because in for example LoginComponent I have RestService dependency and I've got this error:
zone.js:140 Uncaught Error: Error in ./LoginComponent class LoginComponent_Host - inline template:0:0 caused by: process is not defined
ReferenceError: process is not defined
at new RestService (http://localhost:9876/base/src/test.ts:21595:2790)
at DynamicTestModuleInjector.get (DynamicTestModule.ngfactory.js:170:67)
at DynamicTestModuleInjector.get (DynamicTestModule.ngfactory.js:180:93)
at DynamicTestModuleInjector.getInternal (DynamicTestModule.ngfactory.js:255:51)
at DynamicTestModuleInjector.NgModuleInjector.get (http://localhost:9876/base/src/test.ts:25036:27)
at TestBed.get (http://localhost:9876/base/src/test.ts:5589:51)
at _View_LoginComponent_Host0.createInternal (LoginComponent_Host.ngfactory.js:16:74)
at _View_LoginComponent_Host0.AppView.create (http://localhost:9876/base/src/test.ts:36192:21)
at _View_LoginComponent_Host0.DebugAppView.create (http://localhost:9876/base/src/test.ts:36404:44)
I set proccess.env.backendUrl in enviroment.ts (file created by angular-cli).
process.env.backendUrl = 'http://localhost:8080';
export const environment = {
production: false
};
Should I set it somewhere else or is there any method to tell karma about this variable?
If you're using angular-cli, you should just add the backendUrl to the environment.
export const environment = {
production: false,
backendUrl: 'http://localhost:8080'
};
You should also add it in the environment.prod.ts file, setting the url to the production url. When you build in production, the .prod file will be used.
In your files, you should import the environment (from the environment.ts file) and just use environment.backendUrl.
See Also:
Build Targets and Environment Files