In parameterized tests I use hint parameter to clarify test case naming. From the static analyzer point of view this parameter is never used, so this warning from kotlin-maven-plugin appears in the build log:
[WARNING] /Users/test/TestSizeCreation.kt: (42, 10) Parameter 'hint' is never used
How to suppress such warnings globally in all tests?
Example of test with hint:
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
assertThatThrownBy { Size(sizeCandidate) }
.isInstanceOf(InvalidInput::class.java)
.hasMessageStartingWith("Could not recognize size: ")
}
companion object {
#JvmStatic
fun invalidAges(): Stream<Arguments> =
Stream.of(
arguments("negative", -5),
arguments("zero", 0),
arguments("too much", 1000)
)
}
Two possible options (there may be more):
The first is to annotate the parameter as being unused, like this:
#Suppress("UNUSED_PARAMETER") either at the function or parameter level.
The second option is to use a lambda inside your test to execute the actual code, and then use an underscore to ignore the first parameter, like this:
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
class Stack {
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
process(hint, sizeCandidate) { _, size ->
println("add your test using size here $size")
}
}
private fun process(hint: String, sizeCandidate: Int, block: (String, Int) -> Unit) {
block(hint, sizeCandidate)
}
companion object {
#JvmStatic
fun invalidAges(): Stream<Arguments> =
Stream.of(
arguments("negative", -5),
arguments("zero", 0),
arguments("too much", 1000)
)
}
}
I ended up using this function introduced only in the src/test context:
// this function used only to avoid "Parameter is never used" warning
// on intentionally unused parameters
fun Any?.touch() = Unit
This how it looks in a test method:
#ParameterizedTest(name = "Size {index}: {0}")
#MethodSource("invalidAges")
fun shouldFailToCreateAge(hint: String, sizeCandidate: Int) {
hint.touch()
assertThatThrownBy { Size(sizeCandidate) }
.isInstanceOf(InvalidInput::class.java)
.hasMessageStartingWith("Could not recognize size: ")
}
Why:
The #Suppress("UNUSED_PARAMETER") is intended strictly for special situations in rare cases. And would be inappropriate to put it in all Parameterized tests making it noisy. It also could cause missing real cases of unused parameters, helping garbage code appear.
The touch method clearly shows intention. And it looks like a minimal evil.
Related
e.g
type test struct { // few fields}
func (t *test) createresource(res1 string,res2 string)error {
//doing some task
t.createsubresource(res1)
}
func (t *test)createsubresource(res1 string)error{
//perform some task
}
I want to write test function for createresource , how can I mock t.createsubresource(res1) call. This is legacy code and I don't have permission to modify any above function.
Your mock can be done using interfaces, as for example:
main.go
package main
type TestInterface interface {
CreateResource(res1 string, res2 string) error
CreateSubresource (res1 string) error
}
func main() {
DoSomething(new(Test))
}
func DoSomething(t TestInterface) {
t.CreateResource()
}
main_test.go
package main
import "testing"
type TestMock struct {}
func (tm *TestMock) CreateResource(res1 string, res2 string) error {
return nil
}
func (tm *TestMock) CreateSubresource(res1 string) error {
return nil
}
func TestDoSomething(t *testing.T) {
err := DoSomething(new(TestMock))
//... do your assertions
}
Why does it works like that?
Calling a function that depends on a specific structure does not allow you to inject alternatives to it, that's why a solution using interface needs to be created. By having an interface, just implement a new structure that matches that interface and pass it as a dependency injection to the procedure that will be tested.
Also, check this out:
There is no easy way, by default, to just point your original structure and tell Go to make a mock from it. Maybe some 3rd party lib can do it (but I didn't saw that yet).
In go, public and private declarations are defined by the first letter as uppercase. By the lower cases declarations in your sample I've noticed that everything is private.
Usually it is not a good practice to test private methods. There are a lot of discussions about this topic, you can take a look in this one here
There are also some support libs to make assertions and mocks like for example stretchr/testify, please make a research first.
I hope that it helps you.
I have a data class A with a function as follows:
data class A(val a: String) {
fun foo(b: String) = "$a, $b"
}
I attempt the following mock in my test:
fun `whatever`() {
val spy = spyk<A>()
every { spy.a } returns "Tree"
assertThat(spy.foo("Snake")).isEqualTo("Tree Snake")
}
When I run a test written like this it fails with a NullPointerException on the line fun foo... in the data class.
Am I doing anything wrong or is this a bug in MockK?
I have totally different results when I run your code. Firstly it complains that there is no default constructor.
Then I fixed it to use the non-default constructor and it prints "abc Snake"
val spy = spyk(A("abc"))
every { spy.a } returns "Tree"
println(spy.foo("Snake"))
There is a reason for that. Kotlin is accessing a property through a field in foo function. This seems to be an optimization.
MockK is not able to do anything about it right now. There is the following ticket to transform getfield call: https://github.com/mockk/mockk/issues/104
So, while this is quite a kotlin-dsl for gradle specific issue, I think it overall applies to the kotlin language itself, so I am not going to use that tag.
In the gradle API, the class Action<T> is defined as:
#HasImplicitReceiver
public interface Action<T> {
/**
* Performs this action against the given object.
*
* #param t The object to perform the action on.
*/
void execute(T t);
}
So ideally, this should work in kotlin (because it is a class with a SAM):
val x : Action<String> = {
println(">> ${it.trim(0)}")
Unit
}
But I get the following two errors:
Unresolved reference it
Expected Action<String> but found () -> Unit
Fwiw, even Action<String> = { input: String -> ... } doesn't work.
Now here's the really intriguing part. If I do the following in IntelliJ (which btw, works):
object : Action<String> {
override fun execute(t: String?) {
...
}
}
IntelliJ pops the suggestion Convert to lambda, which when I do, I get:
val x = Action<String> {
}
which is better, but it is still unresolved. Specifying it now:
val x = Action<String> { input -> ... }
gives the following errors Could not infer type for input and Expected no parameters. Can someone help me with what is going on?
This is because the Action class in gradle is annotated with HasImplicitReceiver. From the documentation:
Marks a SAM interface as a target for lambda expressions / closures where the single parameter is passed as the implicit receiver of the invocation (this in Kotlin, delegate in Groovy) as if the lambda expression was an extension method of the parameter type.
(emphasis mine)
So, the following compiles just fine:
val x = Action<String> {
println(">> ${this.trim()}")
}
You could even just write ${trim()} and omit the this in front of it.
You need reference the function with class name, like:
val x: Action<String> = Action { println(it) }
I am writing tests for the method provide below.
`
class ScrapedRecipeCache #Autowired constructor(private val cache: RecipeScrapingCacheService,
private val recipeService: RecipeService) : ScrapedRecipeProvider {
override fun provide(request: ScrapingRequest): Flux<ScrapedRecipe> =
cache.retrieve(request.link)
.doOnNext { println(it) }
.flatMap { (link, _, recipeHash, error) ->
recipeService.findByHash(recipeHash)
.map { ScrapedRecipe(it, link, error)}
.switchIfEmpty(cache.remove(request.link).then(Mono.empty()))
}
.flux()
}
`
The test looks as follows:
private val recipeFetched = Recipe("Tortellini", RecipeDifficulty.EASY, 15.0)
val cacheContents = RecipeScrapingResource("www.google.com", ScrapingOrigin.JAMIE_OLIVER, recipeFetched.hash,
mutableListOf(
pl.goolash.core.Exception("aa", ErrorType.WARNING, LocalDateTime.MIN)
))
val request = ScrapingRequest("www.google.com", ScrapingOrigin.JAMIE_OLIVER, 4)
#BeforeEach
fun setUp() {
given(cache.retrieve("www.google.com")).willReturn(Mono.just(cacheContents))
given(recipeService.findByHash(recipeFetched.hash)).willReturn(Mono.just(recipeFetched))
}
#Test
#DisplayName("Then return data fetched from service and don't delete cache")
fun test() {
cacheFacade.provide(request)
.test()
.expectNext(ScrapedRecipe(recipeFetched, "www.google.com", cacheContents.error!!))
.expectComplete()
.verify()
BDDMockito.verify(cache, BDDMockito.never()).remove(request.link)
}
The test fails because cache.remove(request.link) is called. To my understanding (or from what I managed to gather from documentation) switchIfEmpty, should only be fired when recipeService.findByHash returns Mono.empty(). However the debugger shows that it returns mocked value of Mono.just(fetchedRecipe).
The interesting thing is that when I replace
.switchIfEmpty(cache.remove(request.link).then(Mono.empty()))
with
.switchIfEmpty(Mono.just(1).doOnNext{println("weeee")}.then(Mono.empty()))
Then weee is not printed hence it behaves as expected, that is switchIfEmpty is not fired.
Furthermore the tested issue runs properly in integration test and does not clear the cache.
Reactor version : 3.1.0-RC1
Other notable details: Spring Boot 2.0.0-M4, Mockito-core:2.10, junit 5, project is written in kotlin
The question is, does anybody see anything wrong with this? Because I have spent two days over and still have no clue why this behaves so bizzarely.
Finally I found out how to make this work.
In order to remedy it:
override fun provide(request: ScrapingRequest): Flux<ScrapedRecipe> =
cache.retrieve(request.link)
.flatMap { (link, _, recipeHash, error) ->
recipeService.findByHash(recipeHash)
.map { ScrapedRecipe(it, link, error) }
.switchIfEmpty(Mono.just(1)
.flatMap { cache.remove(request.link) }
.then(Mono.empty()))
}
.flux()
You can see how using flatMap to execute the asynch work does the job, even if this is not the neatest implementation, it revealed to me quite an interesting mechanism hidden here.
In C++ I can write:
#ifdef DEBUG
cout << "Debugging!" << endl;
Is there any equivalent in Scala?
The conventional idiom is #elidable.
The scaladoc covers your conventional use case:
http://www.scala-lang.org/api/current/scala/annotation/elidable.html
The equivalent form of a C preprocesser #ifdef is a Scala macro:
package app.macros.log
import scala.language.experimental.macros
import reflect.macros.Context
object SimpleMacroLogger {
private val on = true
def info(msg: String): Unit = macro info_impl
def info_impl(c: Context)(msg: c.Expr[String]): c.Expr[Unit] = {
import c.universe._
if (on) {
reify {
println(msg.splice)
}
} else {
reify {
// Nothing
}
}
}
}
to be used with
import app.macros.log.{SimpleMacroLogger => log}
object SimpleMacroLoggerDemo extends App {
log.info("Hello")
}
It's far more complex to code, but it's usage is superior: There is no need for surrounding #ifdef/#endif etc. So it does not clutter up your code.
If you set on to false, the macro removes the logging completely.
Anything within the reify will go into the resulting byte code,
the other code is run at compile time. This especially applies to the if (on) ....
If you want the code to only be executed when certain conditions hold, you can use a standard if block:
if (SystemProperties.get("debug.mode").exists(_ == "true") {
println("Debugging!")
}
If you're concerned for whatever reason that the statement shouldn't even appear in the compiled output, then you can use an if-block with a compile-time constant expression. In these cases, javac/scalac will correctly infer that the condition will never be true, and so doesn't even include the bytecode for the block. (Obviously you'll need to modify your build to pull in a constant "true" for debug builds, and "false" for prod builds.)
object Constants {
final val DEBUG = false
}
// ...
if (Constants.DEBUG) {
println("Debugging!")
}