I have one instance of wiremock that is used across multiple test classes, It has worked fine until recently, when used to test
async methods, when the test classes are ran singly, tests pass but when the entire tests are ran(mvn test), some of the async class tests fail with
ConditionTimeOut error. The verify is failing because, I presume, the wiremock server was not done when the verify was called and the awaitility library is
waiting for it. Just my understanding based on this links -->
https://github.com/tomakehurst/wiremock/issues/565
https://github.com/tomakehurst/wiremock/issues/574
here is my wiremock class def :
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWireMock(port = 9099)
public class WireMockTest {
#Autowired
public wireMockClassA wireMockClassA;
#Autowired
public wireMockClassB wireMockClassB;
//other definitions here and more wiremock class...
}
here is an example test async class:
public class SaleWireMockTest extends WireMockTest {
#Test
void call_sale_endpoint_and_return_200() {
wireMockClassA.callSaleEndpoint(PATH, request, HttpStatus.OK);
makeAsyncCall();
await().atMost(1, TimeUnit.SECONDS).untilAsserted(() ->
wireMockClassA.verify(1, request));
}
//more test methods here....
}
stack:
java 14
wiremock 2.26.2
Spring boot 2.3.2.RELEASE
Have you tried setting the first poll time?
await().pollDelay(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(3)).untilAsserted(() -> {...});
Related
I am currently running a single test case with wire mock. Following is the code snippet:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class, webEnvironment = DEFINED_PORT)
public class ResolveIT {
#ClassRule
public static WireMockRule wireMockRule = new WireMockRule(8900);
#Autowired
private TestRestTemplate restTemplate;
#BeforeClass
public static void init() {
wireMockRule.resetAll();
}
#Test
public void testA() {
HttpEntity<String> entity = new HttpEntity<String>(null, getRequestHeaders());
ResponseEntity<String> response = restTemplate.exchange(localhost:8080/abc, HttpMethod.GET, entity, String.class);
assertEquals(response.getStatusCode(), HttpStatus.OK);
assertEquals(response.getBody(), "Hey");
}
}
I have placed my stubs in a json file in mappings folder which looks like this:
{
"request": {
"method": "GET",
"url": "/abc/xyz"
},
"response": {
"status": 200,
"bodyFileName": "body.json",
"headers": {
"Content-Type": "application/text",
}
}
}
I run this class as JUnit tests from my IDE. Now I need help with the following scenario:
I wish to run a test suite where multiple classes having such tests will run in parallel, in short, I wish to run wiremock tests in parallel. If I configure all my classes like this, I will have to provide a different port to make them run in parallel which doesnt seems to be a
feasible solution here. Also I read somewhere that wiremock is not thread safe.
How can I make the run thread safe?
How can I configure my code so that wiremock runs on one port and all my tests can run in parallel? What should be code for that and how should that single instance of wiremock be configured and how the test should be run?
To achieve this do I need to make the stubbing manually in each test class or can it be achieved along with dynamic stubbing through json file?
P.S. - I am using maven in my project if it is required to be known.
I'm using spring-integration bundled with spring-batch and got stuck trying to write integration tests to test the whole flow, not just single config.
I've created Embedded Sftp Server for this tests and trying to send message to sftpInboundChannel - the message is sent, but nothing happens, but when i send this message to the next channel (after sftpInboundChannel) it goes ok. Also i'm not able to load test source properties, even though i'm using #TestPropertySource annotation.
This are my class annotations
#TestPropertySource(properties = {
//here goes all the properties
})
#EnableConfigurationProperties
#RunWith(SpringRunner.class)
#Import({TestConfig.class, SessionConfig.class})
#ActiveProfiles("it")
#SpringIntegrationTest
#EnableIntegration
#SpringBootTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
This is my class body
#Autowired
private PollableChannel sftpInboundChannel;
#Autowired
private SessionFactory<ChannelSftp.LsEntry> defaultSftpSessionFactory;
#Autowired
private EmbeddedSftpServer server;
#Test
public void shouldDoSmth() {
RemoteFileTemplate<ChannelSftp.LsEntry> template;
try {
template = new RemoteFileTemplate<>(defaultSftpSessionFactory);
SftpTestUtils.moveToRemoteFolder(template);
final List<ChannelSftp.LsEntry> movedFiles = SftpTestUtils.listFilesFromDirectory("folder/subfolder", template);
log.info("Moved file {}", movedFiles.size());
final MessageBuilder<String> messageBuilder = MessageBuilder.withPayload("Sample.txt") // path to file
.setHeader("file_Path", "Sample.txt")
boolean wasSent = this.sftpInboundChannel.send(messageBuilder.build());
log.info("Was sent to sftpInboundChannel channel {}", wasSent);
log.info("message {}", messageBuilder.build());
} finally {
SftpTestUtils.cleanUp();
}
}
To the case of not read the property file one solution is add in your Test class something like this:
#BeforeClass
public static void beforeClass() {
System.setProperty("propertyfile", "nameOfFile.properties");
}
A second way is to create a xml (or class) config where you add the tag:
<context:property-placeholder
location="nameOfFile.properties"
ignore-resource-not-found="true" system-properties-mode="OVERRIDE" />
and your file will be localized.
The property file should be inside of resources folder.
I am using an abstract class like this:
#SpringBootTest(classes = MyAppApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public abstract class AbstractIntegrationTest {
static {
PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer().withPassword("password")
.withUsername("postgres").withDatabaseName("MyApp");
postgreSQLContainer.start();
System.setProperty("spring.datasource.url", postgreSQLContainer.getJdbcUrl());
System.setProperty("spring.datasource.password", postgreSQLContainer.getPassword());
System.setProperty("spring.datasource.username", postgreSQLContainer.getUsername());
}
Then I have many tests that leverage that use that class like this:
public class moreTests extends AbstractIntegrationTest {
TestRestTemplate restTemplate = new TestRestTemplate("my-user", "password");
HttpHeaders headers = new HttpHeaders();
#Test
public void SimpleHealthCheck() {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(
createURLWithPort("/api/v1/healthcheck"),
HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
#Test
public void GetInst() {
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(
createURLWithPort("/api/v1/institutions"),
HttpMethod.GET, entity, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
However, some of my tests will pollute the database. I'd like to control if a test runs with a fresh database or not. What's the prescribed way to do this?
After more reading about Spring boot integration testing, it appears the prescribed way is to use the "#DirtiesContext" annotation for tests that are destructive (or dirty).
EDIT: After a few months, I realized #DirtiesContext is not awesome. It basically resets the whole app which can be expensive. Also, #DirtiesContext May not reset your database in some cases depending on how your app works. I suggest having a cleanup SQL script that runs in your #BeforeAll or #AfterAll section of each test class. This cleanup SQL script needs to be carefully written.
you either use the #Before annotation to clean everything before executing your tests.
Or you clean in each test before you execute.
Each test should be independent from the other. So usually:
clear and set up expectations
run test
If test fails, your database will be in the failed state so you can check what happened.
I'm struggling with Play and JPA in order to be able to use two different javax.persistence.Entity model associated to two different persistence units (needed to be able to connect to different DB - for example an Oracle and a MySQL db).
The problem come from the Transaction which is always bind to the default JPA persitenceUnit (see jpa.default option).
Here is two controller actions which show the solution I found to manually define the persistence :
package controllers;
import models.Company;
import models.User;
import play.db.jpa.JPA;
import play.db.jpa.Transactional;
import play.mvc.Controller;
import play.mvc.Result;
public class Application extends Controller {
//This method run with the otherPersistenceUnit
#Transactional(value="other")
public static Result test1() {
JPA.em().persist(new Company("MyCompany"));
//Transaction is run with the "defaultPersistenceUnit"
JPA.withTransaction(new play.libs.F.Callback0() {
#Override
public void invoke() throws Throwable {
JPA.em().persist(new User("Bobby"));
}
});
return ok();
}
//This action run with the otherPersistenceUnit
#Transactional
public static Result test2() {
JPA.em().persist(new User("Ryan"));
try {
JPA.withTransaction("other", false, new play.libs.F.Function0<Void>() {
public Void apply() throws Throwable {
JPA.em().persist(new Company("YourCompany"));
return null;
}
});
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
return ok();
}
}
This solution doesn't seem to be really "clean". I'd like to know if you know a better way to avoid the need to manually modify the transaction used.
For this purpose, I created a repo on git with a working sample application which shows how I configured the project.
https://github.com/cm0s/play2-jpa-multiple-persistenceunit
Thank you for your help
i met the same problem, too. too many advices are about PersistenceUnit annotation or getJPAConfig. but both them seem not work in play framework.
i found out a method which works well in my projects. maybe you can try it.
playframework2 how to open multi-datasource configuration with jpa
gud luk!
Is there a way to call a method in a Grails service, from a Scala class that is running on the same JVM?
I have seen something similar done from Groovy/Griffon but cannot figure out how to accomplish that in Grails. (http://www.jroller.com/aalmiray/entry/griffon_groovy_scala_working_together)
Basically, one of my Grails controllers calls some Scala code, which should return some values asynchronously. So, I guess, the only way to return those values is by calling back a method in a Grails service.
I found a way of doing it, inspired by the link in the question above, and one of the FAQs in the Grails website.
On the Scala side:
Declare an object similar to the following:
package scalaCallback
object ScalaCallback{
var cback: {def callback(example: String)} = null
def setCallback(cb: {def callback(example: String)}){
cback = cb
}
def invokeCallback(example: String){
if(callback != null) cback.callback(example)
}
}
On the Grails side:
Create a class in src/groovy similar to the following:
package groovyCallback
import org.codehaus.groovy.grails.commons.ApplicationHolder
class GroovyCallback{
private GroovyCallback() {}
private static final INSTANCE = new GroovyCallback()
static getInstance(){ return INSTANCE }
void callback(String example){
ApplicationHolder.application.mainContext.yourService.yourMethod(example)
}
}
In your BootStrap.groovy init add the following:
scalaCallback.cback = groovyCallback.GroovyCallback.getInstance()
When you call invokeCallback("example") in Scala, it will call yourService.yourMethod("example")
Note: the jar file with your Scala class should be in the lib folder of you Grails application
Your Grails service is a Spring bean. #Autowire the service into your Scala class (it will need to be a bean/#Component) and call the method.
EDIT - added example:
For example (using Java, not Scala but the approach is exactly the same):
Java code calling service:
package grailstest;
#Component
public class ServiceInjectionTester {
#Autowired TestService testService;
public String testTheService() {
return testService.serviceMethod();
}
}
Service:
class TestService {
String serviceMethod() {
return "success"
}
}
In Config.groovy:
grails.spring.bean.packages = [ "grailstest" ]
You can also wire your Java/Scala bean into your Grails classes:
class TestController {
#Autowired
ServiceInjectionTester serviceInjectionTester
def index = {
render(text: serviceInjectionTester.testTheService())
}
}
References:
Grails Reference 8.4 - Using Services from Java
Spring: The Foundation for Grails