Groovy Spock BlockingVariable never released - unit-testing

I am fighting a loosing battle against Spock unit tests in my Grails application. I want to test async behavior and in order to get familiar with Spock's BlockingVariable I've written this simple sample test.
void "test a cool function of my app I will not tell you about"() {
given:
def waitCondition = new BlockingVariable(10000)
def runner = new Runnable() {
#Override
void run() {
Thread.sleep(5000)
waitCondition.set(true)
}
}
when:
new Thread(runner)
then:
true == waitCondition.get()
}
Unfortunately it is not a good thing, because otherwise it would come to an end. When I set a breakpoint at Thread.sleep() and debug the test, that breakpoint is never hit. What am I missing?

Your test is broken, because you don't actually run the thread you create. Instead:
when:
new Thread(runner)
you should do:
when:
new Thread(runner).run()
and then your test succeeds after approximately 5 seconds.

Related

ReSharper not supporting Assert.That

I'm in the process of returning to ReSharper recently, using trial of the newest version - 2022.2.3. I've got quite surprised when one of my nUnit tests failed in a weird way, when run by Resharper's built in Unit Test runner. Something that has never happened to me with a Test Explorer.
As long as the Asserts pass, it's all fine - green, all tests are listed. However, when the assert fails, it says One or more child tests had errors. Exception doesn't have a stacktrace
Not only there is no mention of actual values that weren't correct, but the whole failing test seems to be gone!
This happens only when I use the 'modern' approach with Assert.That. So
Assert.That(httpContext.Response.StatusCode, Is.EqualTo(200));
is causing issues, meanwhile, the more classic:
Assert.AreEqual(200, httpContext.Response.StatusCode);
works as expected. Is that something that is a known bug, or maybe some attributes are required? JetBrains claims they have full support of nUnit out of the box, so that is a bit surprising.
NOTE: the tests methods are async, awaiting result and returning Tasks, beside this nothing unusual.
EDIT: The test code is as follows, ApiKeyMiddleware is any middleware that returns response with 200 here.
[TestFixture]
public class ApiKeyMiddlewareTests
{
[Test]
public async Task Invoke_ActiveKey_Authorized()
{
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers.Add("XXXXX", "xxxx");
var configuration = Options.Create(new AccessConfiguration { ActiveApiKeys = new List<string> { "xxxx" } });
var middleware = new ApiKeyMiddleware(GetEmptyRequest(), configuration);
await middleware.Invoke(httpContext);
Assert.That(httpContext.Response.StatusCode, Is.EqualTo(200)); //change to anything else than 200 and it fails + vanishes
}
}

Flink Job Testing with MiniClusterWithClientResource

I've wrote a #Test method in order to test the execuction of a Flink job.
This is the method:
#Test
void testFlinkJob() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(2);
MyJob.buildJob(env, new MySourceFunction(), new MySinkFunction());
env.execute();
//asserts
}
Implementations details of MyJob.buildJob(), MySourceFunction and MySinkFunction are not important. Please, focus on env.setParallelism(2).
If I run this test, everything is ok. Fine!
However, Flink official documentation (https://nightlies.apache.org/flink/flink-docs-release-1.14/docs/dev/datastream/testing/#junit-rule-miniclusterwithclientresource), speaks about MiniClusterWithClientResource .
So I added these snippet to my test class, as showed into documentation.
#ClassRule
public static MiniClusterWithClientResource flinkCluster =
new MiniClusterWithClientResource(
new MiniClusterResourceConfiguration.Builder()
.setNumberSlotsPerTaskManager(2)
.setNumberTaskManagers(1)
.build());
I run my test again and it still passes. Perfect!
Then I started to play with the above snippet. The first thing I changed is the value of setNumberSlotsPerTaskManager() param from 2 to 1.
I launched a one more time my test. This time I expected a test failure because the value of parallelism (2) is higher than the value numberOfTaskManager * numberSlotPerTestManagers (1).
Instead, my test continues to pass.
Same thing if I write setNumberTaskManagers(0) (No TaskManager). Test continues to pass.
Seems that MiniClusterWithClientResource is dummy. Can you help my to understand how it work, please?
If you are working with JUnit 5, #ClassRule annotation will be ignored. You need to use extensions:
#ExtendWith(MiniClusterExtension.class)
public class MyTest {
#RegisterExtension
public static final MiniClusterExtension MINI_CLUSTER_RESOURCE = new MiniClusterExtension(
new MiniClusterResourceConfiguration.Builder()
.setNumberSlotsPerTaskManager(2)
.setNumberTaskManagers(1)
.build());
}
P.S.: MiniClusterExtension.class is still marked as #Experimental as of v1.16 and therefore subject to changes.

kotlin multiplatform library simple http get request test

I am new to kotlin multiplatform library.
I wanted to make a simple HTTP get request and test if it works.
here is what I have so far.
this is in the commonMain package
import io.ktor.client.*
import io.ktor.client.request.*
object HttpCall {
private val client: HttpClient = HttpClient()
suspend fun request(url: String): String = client.get(url)
}
and here is my attempt to test
#Test
fun should_make_http_call() {
GlobalScope.launch {
val response = HttpCall.request("https://stackoverflow.com/")
println("Response: ->$response")
assertTrue { response.contains("Stack Overflow - Where Developers Learn") }
assertTrue { response.contains("text that does not exist on stackoverflow") }
}
Now, this should fail because of the second assert but it doesn't.
no matter what I do the test always passes.
and printing the response does not work either
what am I doing wrong here?
The test function will run in a single thread, and if the function ends without failing, the test passes. GlobalScope.launch starts an operation in a different thread. The main test thread will finish before the network calls get a chance to run.
You should be calling this with something like runBlocking, but testing coroutines in general, and ktor specifically, on Kotlin native, is not easy because there's no easy way to have the suspended function continue on your current thread.
I will not use the GlobalScope or the runBlocking because they are not really made for Unit Test. Instead, I will use runTest.
Here are the steps:
Check your build.gradle and make sure you do have under commontTest the lib 'kotlinx-coroutines-test' set
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${Version.kotlinCoroutines}")
...
}
}
Then into your directory commonTest, create a file and run
#Test
fun should_make_http_call() = runTest {
val response = HttpCall.request("https://stackoverflow.com/")
println("Response: ->$response")
assertTrue { response.contains("Stack Overflow - Where Developers Learn") }
assertTrue { response.contains("text that does not exist on stackoverflow") }
}
Extra:
runTest does not handle exceptions very well, so if you are interested in making to catch any exceptions if happens. Change runTest for runReliableTest, You can get the code from this link https://github.com/Kotlin/kotlinx.coroutines/issues/1205#issuecomment-1238261240

How to unit test a synchronous method calling asynchronous method?

What is the correct way to write a unit test for a synchronous method calling async methods.
Right now my unit test are passing, but when I try to open the page, it never returns.
Why isn't my unit test failing? How can I make it fail?
I replicated my problem with this simple code:
My passing test:
[TestMethod]
public void DoSomeWork_WhenWeDoSomeWork_ShouldReturnDone()
{
var service = new SyncService();
const string expected = "Done";
var actual = service.DoSomeWork();
Assert.AreEqual(expected, actual);
}
My view that never returns:
public ActionResult Index()
{
var syncService = new SyncService();
return View((object)syncService.DoSomeWork());
}
My service that never returns to view:
public class SyncService
{
public string DoSomeWork()
{
return SomeWork().GetAwaiter().GetResult();
}
private async Task<string> SomeWork()
{
var task1 = Task.Delay(1000);
var task2 = Task.Delay(1000);
await Task.WhenAll(task1, task2);
return "Done";
}
}
I don't think I can help you with this specific example, but I think a good general strategy is to write two tests. One to test if the synchronous method passes the correct data and an other to test if the asynchronous method works properly.
I mostly work in JavaScript and that general approach works for me. Also you can check the documentation of your testing frameworks, maybe it provides some methods for this.
First, don't block on async code (link to my blog). By blocking on async code, you're actually causing a deadlock. This deadlock does not happen in your unit test because unit tests run in a thread pool context, not an ASP.NET context (link to my blog).
There are good reasons for not having synchronous wrappers for asynchronous methods. So I recommend getting rid of DoSomeWork completely, leaving only SomeWork (renamed to SomeWorkAsync).
To solve your problem, you should use asynchronous controller actions.

Running TestNG test sequentially with time-gap

I have couple of DAO unit test classes that I want to run together using TestNG, however TestNG tries to run them in parallel which results in some rollbacks failing. While I would like to run my Unit Test classes run sequentially, I also want to be able to specify a minimum time that TestNG must wait before it runs the next test. Is this achievable?
P.S. I understand that TestNG can be told to run all the tests in a test class in a SingleThread, I am able to specify the sequence of method calls anyway using groups, so that's not an issue perhaps.
What about a hard dependency between the 2 tests? If you write that:
#Test
public void test1() { ... }
#Test(dependsOnMethods = "test1", alwaysRun = true)
public void test2() { ... }
then test2 will always be run after test1.
Do not forget alwaysRun = true, otherwise if test1 fails, test2 will be skipped!
If you do not want to run your classes in parallel, you need to specify the parallel attribute of your suite as false. By default, it's false. So I would think that it should run sequentially by default, unless you have some change in the way you invoke your tests.
For adding a bit of delay between your classes, you can probably add your delay logic in a method annotated with #AfterClass. AFAIK testng does not have a way to specify that in a testng xml or commandline. There is a timeout attribute but that is more for timing out tests and is not probably what you are looking for.
For adding delay between your tests i.e. test tags in xml, then you can try implementing the ITestListener - onFinish method, wherein you can add your delay code. It is run after every <test>. If a delay is required after every testcase, then implement delay code in IInvokedMethodListener - AfterInvocation() which is run after every test method runs. You would need to specify the listener when you invoke your suite then.
Hope it helps..
Following is what I used in some tests.
First, define utility methods like this:
// make thread sleep a while, so that reduce effect to subsequence operation if any shared resource,
private void delay(long milliseconds) throws InterruptedException {
Thread.sleep(milliseconds);
}
private void delay() throws InterruptedException {
delay(500);
}
Then, call the method inside testing methods, at end or beginning.
e.g
#Test
public void testCopyViaTransfer() throws IOException, InterruptedException {
copyViaTransfer(new File(sourcePath), new File(targetPath));
delay();
}