Why are JUnit5 Parametrized tests using argument providers not defined in #ArgumentSource? - java

I have a problem with my parameterized tests.
#ParameterizedTest
#ArgumentsSource(CorrectMessagesArgumentProvider.class)
void shouldSendMessageForCorrectConfiguration(SmtpConfiguration configuration) {
var expectedMessageBody = fetchMessage();
var alertSender = new AlertSender(configuration);
var alertSubject = subjectFrom();
alertSender.send(expectedMessageBody, alertSubject);
var receivedMessages = greenMail.getReceivedMessages();
assertEquals(1, receivedMessages.length);
}
#ParameterizedTest
#ArgumentsSource(IncorrectMessagesArgumentProvider.class)
void shouldNotSendMessageForIncorrectConfiguration(SmtpConfiguration smtpConfiguration) {
var expectedMessageBody = fetchMessage();
var alertSender = new AlertSender(smtpConfiguration);
var alertSubject = subjectFrom();
var expectedErrorMessage = "Error sending alert";
var actualErrorMessage =
assertThrows(
SendAlertException.class, () -> alertSender.send(expectedMessageBody, alertSubject));
assertTrue(actualErrorMessage.getMessage().contains(expectedErrorMessage));
}
When I run those tests separetly, they work correctly. But when I run suite, the second test running fails, because it is using arguments from the other test.
They're somehow sharing that resource, but I have no idea how. Any ideas?

Okey, I got it - deep in the class responsible for sending emails, I was creating session object by getDefaultInstance(). It was creating singleton which was available for all JVM processes. When I used getInstance() - it work like a charm.

Related

Passing parameters to gradle build script

I'm trying to execute a such command in the console:
./gradlew cucumber -Pthreads=80 -Ptags=#ALL_API_TESTS
in the build.gradle:
cucumber {
threads = "$threads"
glue = 'classpath:com.sixtleasing.cucumber.steps'
plugin = ['pretty']
tags = "$tags"
featurePath = 'src/main/resources/feature'
main = 'cucumber.api.cli.Main'
}
but it doesnt work :( How can I fix it?
Your original expression set threads to a String value, when it is clearly a numeric one, so you need to use something like:
int threadsNum = "$threads".toInteger()
cucumber {
threads = threadsNum
glue = 'classpath:com.sixtleasing.cucumber.steps'
plugin = ['pretty']
tags = "$tags"
featurePath = 'src/main/resources/feature'
main = 'cucumber.api.cli.Main'
}
Hope this helps.

Is there a way to stop multi thread tests for don't interfere in each other in the database side?

I'm implementing tests for a multithreaded microservice, and I'm afraid that the tests that make checks in the database do not interfere with each other, do exites a way?
The tests are mos of them like that:
#Test
#Transactional
public void createRefillOfferEvent() throws Exception {
int databaseSizeBeforeCreate = refillOfferEventRepository.findAll().size();
// Create the RefillOfferEvent
RefillOfferEventDTO refillOfferEventDTO = refillOfferEventMapper.toDto(refillOfferEvent);
restRefillOfferEventMockMvc.perform(post("/api/refill-offer-events")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(refillOfferEventDTO)))
.andExpect(status().isCreated());
// Validate the RefillOfferEvent in the database
List<RefillOfferEvent> refillOfferEventList = refillOfferEventRepository.findAll();
assertThat(refillOfferEventList).hasSize(databaseSizeBeforeCreate + 1);
RefillOfferEvent testRefillOfferEvent = refillOfferEventList.get(refillOfferEventList.size() - 1);
//assertThat(testRefillOfferEvent.getRequestDate()).isEqualTo(DEFAULT_REQUEST_DATE);
assertThat(testRefillOfferEvent.getRequesttransactionid()).isEqualTo(DEFAULT_REQUESTTRANSACTIONID);
assertThat(testRefillOfferEvent.getMsisdn()).isEqualTo(DEFAULT_MSISDN);
assertThat(testRefillOfferEvent.getPlatform()).isEqualTo(DEFAULT_PLATFORM);
assertThat(testRefillOfferEvent.getOfferId()).isEqualTo(DEFAULT_OFFER_ID);
assertThat(testRefillOfferEvent.getOfferName()).isEqualTo(DEFAULT_OFFER_NAME);
assertThat(testRefillOfferEvent.getOfferAmount()).isEqualTo(DEFAULT_OFFER_AMOUNT);
assertThat(testRefillOfferEvent.getOfferProfileId()).isEqualTo(DEFAULT_OFFER_PROFILE_ID);
assertThat(testRefillOfferEvent.getResponseStatus()).isEqualTo(DEFAULT_RESPONSE_STATUS);
assertThat(testRefillOfferEvent.getResponseCode()).isEqualTo(DEFAULT_RESPONSE_CODE);
assertThat(testRefillOfferEvent.getResponseDescription()).isEqualTo(DEFAULT_RESPONSE_DESCRIPTION);
assertThat(testRefillOfferEvent.getInfo1()).isEqualTo(DEFAULT_INFO_1);
assertThat(testRefillOfferEvent.getInfo2()).isEqualTo(DEFAULT_INFO_2);
assertThat(testRefillOfferEvent.getInfo3()).isEqualTo(DEFAULT_INFO_3);
assertThat(testRefillOfferEvent.getInfo4()).isEqualTo(DEFAULT_INFO_4);
assertThat(testRefillOfferEvent.getInfo5()).isEqualTo(DEFAULT_INFO_5);
// Validate the RefillOfferEvent in Elasticsearch
RefillOfferEvent refillOfferEventEs = refillOfferEventSearchRepository.findOne(testRefillOfferEvent.getId());
assertThat(refillOfferEventEs).isEqualToIgnoringGivenFields(testRefillOfferEvent);
}`
That's what i get
Failed tests:
RefillOfferEventResourceIntTest.deleteRefillOfferEvent:394
Expected size:<6> but was:<7> in:

Mockito Unit tests - Timestamps are different

Having some issues with a Mockito test.
I currently get this error:
Argument(s) are different! Wanted:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity#3e437e6c
);
-> at uk.co.withersoft.docservice.datastore.impl.MetaDataStoreImplTest.storeClaimMetadata(MetaDataStoreImplTest.java:55)
Actual invocation has different arguments:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity#3e361ee2
);
I'm pretty sure its because the times within MetaDataEntity are different
//This is what I should be getting
id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp#1517} "2018-07-25 18:39:21.993"
createdDate = {Timestamp#1518} "2018-07-25 18:39:21.993"
// This is actually what I get.
id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp#1530} "2018-07-25 18:39:49.274"
createdDate = {Timestamp#1531} "2018-07-25 18:39:52.716"
Here is my test case:
#Test
public void storeClaimMetadata () throws JsonProcessingException {
ClaimMetaData metaData = constructMetaData();
MetaDataEntity mockResponseMetaDataEntity = new MetaDataEntity();
mockResponseMetaDataEntity.setId(1);
when(repository.save(any(MetaDataEntity.class))).thenReturn(mockResponseMetaDataEntity);
Integer result = testSubject.storeClaimMetadata(metaData);
assertEquals(Integer.valueOf(1), result);
final ObjectMapper mapper = new ObjectMapper();
String jsonMetaData = mapper.writeValueAsString(metaData);
MetaDataEntity expectedMetaDataEntity = new MetaDataEntity(null,
jsonMetaData,
0,
"Saved MetaData to DB",
new Timestamp(System.currentTimeMillis()),
new Timestamp(System.currentTimeMillis()));
Mockito.verify(repository, times(1)).save(expectedMetaDataEntity);
}
//Creates a ClaimRequest
private ClaimMetaData constructMetaData() {
final ClaimMetaData metaData = new ClaimMetaData("CN00000001",
"LN00000001",
"REJ",
"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter");
return metaData;
}
Any help would be much appreciated. This has been driving me crazy!!
This is exactly why people use dependency injection, so they can specify test collaborators that give back predictable results. Replace the hardcoded new Timestamp(System.currentTimeMillis) stuff with calls to Timestamp.from(Instant.now(clock)).
java.time.Clock is an interface that you can use to get your timestamp values. The real implementation can be injected into the code being tested, using one of the factory methods that returns a system clock, like this (using Spring Java configuration):
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
and for the test code you can have an implementation where you specify the time you want the clock to return:
#Before
public void setUp() {
clock = Clock.fixed(date.toInstant(), ZoneId.of("America/NewYork"));
systemUnderTest.setClock(clock);
}
This is "works as designed".
You are invoking a service that computes timestamps. Like, now.
Then you have a test case that has some setup going on, and fetches time stamps, too. Now.
Guess what: albeit these two "nows above are close to each other, there is still a bit of delay between them.
You are checking for equality, can only work when the time stamps are identical! But they aren't, because they are created one after the other, with very well noticeable delays in between!
Meaning: you need to look how you could control which timestamps are created within your application, like saying "the timestamps should be t1 and t2". So that your test can then check "I found t1 and t2".
Alternatively, you simply change your verification step: instead of trying to have "equal" objects (that can't be equal because different time stamps!), you could compare those parts that should be equal, and for the time stamps, you could check that they are "close enough".
In Code , instead of using new Timestamp(System.currentTimeMillis()) , you can use
new Timestamp(DateTimeUtils.currentTimeMillis()). Here DateTimeUtils is from jodatime.
In test cases, can use below.
private SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss:SSS");
#Before
public void before() throws Exception {
// define a fixed date-time
Date fixedDateTime = DATE_FORMATTER.parse("01/07/2016 16:45:00:000");
DateTimeUtils.setCurrentMillisFixed(fixedDateTime.getTime());
}
#After
public void after() throws Exception {
// Make sure to cleanup afterwards
DateTimeUtils.setCurrentMillisSystem();
}````

Running a Java-based Spark Job on spark-jobserver

I need to run an aggregation Spark job using spark-jobserver using low-latency contexts. I have this Scala runner to run a job on using a Java method from a Java class.
object AggregationRunner extends SparkJob {
def main(args: Array[String]) {
val ctx = new SparkContext("local[4]", "spark-jobs")
val config = ConfigFactory.parseString("")
val results = runJob(ctx, config)
}
override def validate(sc: SparkContext, config: Config): SparkJobValidation = {
SparkJobValid;
}
override def runJob(sc: SparkContext, config: Config): Any = {
val context = new JavaSparkContext(sc)
val aggJob = new ServerAggregationJob()
val id = config.getString("input.string").split(" ")(0)
val field = config.getString("input.string").split(" ")(1)
return aggJob.aggregate(context, id, field)
}
}
However, I get the following error. I tried taking out the content returned in the Java method and am now just returning a test string, but it still doesn't work:
{
"status": "ERROR",
"result": {
"message": "Ask timed out on [Actor[akka://JobServer/user/context-supervisor/single-context#1243999360]] after [10000 ms]",
"errorClass": "akka.pattern.AskTimeoutException",
"stack": ["akka.pattern.PromiseActorRef$$anonfun$1.apply$mcV$sp(AskSupport.scala:333)", "akka.actor.Scheduler$$anon$7.run(Scheduler.scala:117)", "scala.concurrent.Future$InternalCallbackExecutor$.scala$concurrent$Future$InternalCallbackExecutor$$unbatchedExecute(Future.scala:694)", "scala.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:691)", "akka.actor.LightArrayRevolverScheduler$TaskHolder.executeTask(Scheduler.scala:467)", "akka.actor.LightArrayRevolverScheduler$$anon$8.executeBucket$1(Scheduler.scala:419)", "akka.actor.LightArrayRevolverScheduler$$anon$8.nextTick(Scheduler.scala:423)", "akka.actor.LightArrayRevolverScheduler$$anon$8.run(Scheduler.scala:375)", "java.lang.Thread.run(Thread.java:745)"]
}
}
I am not too sure why there is a timeout since I am only returning a string.
EDIT
So I figured out that the issue was occurring because I was using a Spark context that was created before updating a JAR. However, now that I try to use JavaSparkContext inside the Spark job, it returns to the error shown above.
What would be a permanent way to get rid of the error.
Also, would the fact that I am running a heavy Spark job on a local docker container be a plausible reason for the timeout.
For resolving ask time out issue, please add/change below properties in jobserver configuration file.
spray.can.server {
idle-timeout = 210 s
request-timeout = 200 s
}
for more information take a look at this https://github.com/spark-jobserver/spark-jobserver/blob/d1843cbca8e0d07f238cc664709e73bbeea05f2c/doc/troubleshooting.md

Test WebSocket in PlayFramework

I have a WebSocket in my Play application and I want to write a test for it, but I couldn't find any example on how to write such a test. I found a discussion in the play-framework Google group but there has been no activity recently.
So, are there any ideas on how to test WebSocket's in a Java test?
You can retrieve underlying Iteratee,Enumerator and test them directly. This way you don't need to use a browser. You need akka-testkit though, to cope with asynchronous nature of iteratees.
A Scala example:
object WebSocket extends Controller {
def websocket = WebSocket.async[JsValue] { request =>
Future.successful(Iteratee.ignore[JsValue] -> Enumerator.apply[JsValue](Json.obj("type" -> "error")))
}
}
class WebSocketSpec extends PlaySpecification {
"WebSocket" should {
"respond with error packet" in new WithApplication {
val request = FakeRequest()
var message: JsValue = null
val iteratee = Iteratee.foreach[JsValue](chunk => message = chunk)(Akka.system.dispatcher)
Controller.websocket().f(request)(Enumerator.empty[JsValue],iteratee)
TestKit.awaitCond(message == Json.obj("type" -> "error"), 1 second)
}
}
}
I test WebSockets code using Firefox:
https://github.com/schleichardt/stackoverflow-answers/commit/13d5876791ef409e092e4a097f54247d851e17dc#L8R14
For Java it works similar replacing 'HTMLUNIT' with 'FIREFOX': http://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Chrome provides a plugin to test websocket service.
Edit
So using the plugin (as shown in picture below) you can provide websocket url and the request data and send message to service. And message log shows the message sent from client and also service response.
Assume that you have a websocket library that returns the Future[Itearatee[JsValue, Unit], Enumerator[JsValue]] your controller uses
trait WSLib {
def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
}
And you wanna test this library.
Here is a context you can use:
trait WebSocketContext extends WithApplication {
val aSecond = FiniteDuration(1, TimeUnit.SECONDS)
case class Incoming(iteratee: Iteratee[JsValue, Unit]) {
def feed(message: JsValue) = {
iteratee.feed(Input.El(message))
}
def end(wait: Long = 100) = {
Thread.sleep(wait) //wait until all previous fed messages are handled
iteratee.feed(Input.EOF)
}
}
case class OutGoing(enum: Enumerator[JsValue]) {
val messages = enum(Iteratee.fold(List[JsValue]()) {
(l, jsValue) => jsValue :: l
}).flatMap(_.run)
def get: List[JsValue] = {
Await.result(messages, aSecond)
}
}
def wrapConnection(connection: => Future[Iteratee[JsValue, Unit], Enumerator[JsValue]]): (Incoming, OutGoing) = {
val (iteratee, enumerator) = Await.result(conn, aSecond)
(Incoming(iteratee), OutGoing(enumerator))
}
}
Then your tests can be written as
"return all subscribers when asked for info" in new WebSocketContext {
val (incoming, outgoing) = wrapConnection(myWSLib.connect)
incoming.feed(JsObject("message" => "hello"))
incoming.end() //this closes the connection
val responseMessages = outgoing.get //you only call this "get" after the connection is closed
responseMessages.size must equalTo(1)
responseMessages must contain(JsObject("reply" => "Hey"))
}
Incoming represent the messages coming from the client side, while the outgoing represents the messages sent from the server. To write test, you first feed in the incoming messages from incoming and then close the connection by calling incoming.end, then you get the complete list of outgoing messages from the outgoing.get method.

Categories

Resources