MockK - verify failing with arguments not matching - mockk

I've noticed that sometimes verify fails with "... call to ... happened, but arguments are not matching"
Here is a sample test that shows verify failing:
class TestStuff {
val stuff = "1"
#RelaxedMockK
lateinit var testService: TestService
#RelaxedMockK
lateinit var testInterface: TestInterface
#Before
fun setup() {
MockKAnnotations.init(this)
every { testInterface.testStuff } returns stuff
}
#Test
fun testStuffCalled() {
testService.testStuff(testInterface.testStuff)
verify { testService.testStuff(testInterface.testStuff) }
}
}
interface TestInterface {
val testStuff: String
}
class TestService {
fun testStuff(stuff: String) {
}
}
If I change the line with the verify call to the following 2 lines, then it works:
let testStuffCopy = testInterface.testStuff
verify { testService.testStuff(testStuffCopy) }

I'm unsure if this is a bug, but a quick workaround would be to use stuff as the verification, as you want the returned value to be it:
verify { testService.testStuff(stuff) }
This way you still test that the behaviour was called, and as you mocked the return of testInterface to return stuff, this should work.
I created an Issue in Mockk for this, and I'll update this answer when something is updated there.

Related

Quarkus #CacheResult is not working properly

I am trying to use quarkus-cache by following the appropriate quarkus doc. I have the below code setup
#ApplicationScoped
class MyClass {
public result doSomething() {
String remoteData = getRemoteData(url);
}
#CacheResult(cacheName = "myCacheName")
public String getRemoteData(String url) {
return remoteCall(url);
}
}
Usage
// Grpc impl class
// call to Myclass.doSomething()
Execution is not proceeding further when getRemoteData() is called the first time. Also, not getting any error.
Am I missing something?

How to write unit test for Kotlin delete by id method?

I have this method
fun delete(id: Long) {
NotFoundExceptionValidator(!dishOfTheDayEntityRepository.existsById(id), "dishOfTheDay not found")
dishOfTheDayEntityRepository.deleteById(id)
}
NotFoundExceptionValidator this just checks if it's null then throws error
this is what I tried
#ConcurrentExecution
internal class DishOfTheDayServiceTest {
private val repo: DishOfTheDayEntityRepository = mockk()
private val mapper: DishOfTheDayMapper = mockk()
private val dishOfTheDayEntityService = DishOfTheDayService(repo, mapper)
#Test
fun `delete should work properly`() {
//given
val id: Long = 1;
//when
dishOfTheDayEntityService.delete(1)
//then
verify(exactly = 1) { repo.deleteById(1) }
}
}
when i run it it throws this error
no answer found for: DishOfTheDayEntityRepository(#1).existsById(1)
io.mockk.MockKException: no answer found for: DishOfTheDayEntityRepository(#1).existsById(1)
You forgot to mock your mocks behaviour, i.e. you should explicitly specify what the existsById() and deleteById() methods return. For example for existsById() it should look like:
every { repo.existsById(id) } returns true
I suppose that the deleteById() method returns Unit so if you don't want to do it like above you can mock DishOfTheDayEntityRepository like:
private val repo: DishOfTheDayEntityRepository = mockk(relaxUnitFun = true)
Now you don't have to mock Unit returning methods of DishOfTheDayEntityRepository. You can find more about it here.

MacOS specific code with Compose Multiplatform

I'm using Compose Multiplatform to write an app for MacOS. But I want to check if I have an internet connection. Preferably unmetered (so no hotspot). I have found some code for MacOS to check that. But when I create an expect class it complains about the actual class for jvmMain. But I want to put that part in macOSMain. If I try to add an empty class in jvmMain it takes that class instead of macOSMain. So I'm not sure how to implement this?
Here is a part of my build.gradle.kts:
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
withJava()
}
macosArm64("macOS")
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
}
val jvmMain by getting {
dependsOn(commonMain)
dependencies {
implementation(compose.desktop.currentOs)
}
}
val macOSMain by getting {
dependsOn(commonMain)
}
}
}
In commonMain I put this for testing:
expect class Test {
fun test(): String
}
In macOSMain I put this:
actual class Test {
actual fun test(): String {
return "MacOS"
}
}
And in jvmMain I put this:
actual class Test {
actual fun test(): String {
return "JVM"
}
}
And to call the function in jvmMain:
fun main() = application {
println("test: ${Test().test()}")
Window(onCloseRequest = ::exitApplication) {
App()
}
}
Which unfortunately prints "JVM". What do I need to do to make it print "MacOS"? Preferably without implementing the class in jvmMain. I also tried expect class in jvmMain, but it then complained about the function not being there in jvmMain.

How to configure Selenide remote grid url in Selenium-Jupiter test framework?

I am trying to configure a Selenide driver within the Selenium-Jupiter framework, to use my remote grid url but it keeps ignoring the configuration, and just runs the local installed browser. Here is how I am trying to configure it. Any idea what might be wrong here?
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.SelenideConfig;
import io.github.bonigarcia.seljup.SelenideConfiguration;
import static com.codeborne.selenide.Browsers.CHROME;
public abstract class ChromeTest extends BaseTest {
#SelenideConfiguration
SelenideConfig selenideConfig = new SelenideConfig();
private String getSeleniumRemote() {
System.getProperty("selenide.remote", "");
}
public ChromeTest() {
if (getSelenideRemote().isEmpty()) {
selenideConfig.proxyEnabled(false)
.browser(CHROME).startMaximized(false)
.browserSize("800x1200").browserPosition("50x60");
} else {
Configuration.timeout = 6000;
Configuration.remote = getSelenideRemote();
selenideConfig.proxyEnabled(false)
.startMaximized(true).browser(CHROME);
}
}
}
I know the regular RemoteWebDriver works and I can get that working but I am hoping to use Selenide in the above example:
Example:
#Test
void testWithRemoteSelenide(#DriverUrl("http://127.1:4444/wd/hub")
#DriverCapabilities("browserName=" + CHROME) SelenideDriver driver)
I can get it to work with the annotation, but the problem is that I need that annotation to be conditional on passing a param to the tests. I want to be able to easily switch using grid or local. Thanks for your help anyone.
Ok, after almost 48 hours an no reponse, I finally figured out the solution. Here it is:
//build.gradle
test {
useJUnitPlatform()
ignoreFailures = false
beforeTest { descriptor ->
logger.lifecycle("Running test: $descriptor.className")
}
systemProperty "env", System.getProperty("env")
def remote = System.getProperty("selenide.remote", "")
if (!remote.isEmpty()) {
systemProperty("selenide.remote", remote)
}
}
Then, in my test base class:
public abstract class ChromeTest extends BaseTest {
#SelenideConfiguration
SelenideConfig selenideConfig = new SelenideConfig();
/**
* This config is equivilant to the documented method:
* Example: test(#DriverUrl("http://127.1:4444/wd/hub")
* #DriverCapabilities("browserName=chrome") SelenideDriver sd)
*/
public ChromeFormTest() {
if (getSelenideRemote().isEmpty()) {
selenideConfig.proxyEnabled(false).proxyHost("http://proxy.domain.com")
.proxyPort(8080)
.browser(CHROME).startMaximized(false)
.browserSize("800x1200").browserPosition("50x60");
} else {
Configuration.timeout = 6000;
Configuration.remote = getSelenideRemote();
selenideConfig.proxyEnabled(false).proxyHost("http://proxy.domain.com")
.proxyPort(8080)
.startMaximized(false).browser(CHROME);
}
}
}
Then, when I execute, it looks like this:
gradle clean test -Denv=sys -Dselenide.remote=http://127.1:4444/wd/hub
--info --tests com.qa.suite.*
And the constructor of each test looks like:
#Test
public void testWhatever(SelenideDriver sd) {

Test Observable.FlatMap Mockito

I've been looking on internet but haven't found the solution if any (new on UnitTest and Mockito)
It's possible to test a method that return a call of a service and manipulate it's result before to return it? Example;
public Observable<Reports> getUserReports(Integer userId) {
return serviceClient
.getReports(userId)
.flatMap(serviceReports -> {
System.out.println("Testing inside flatMap"); <- never reach this line therefore duno if methods down here are invoked and work perfectly
final Observable<List<Report>> reports = getPendingReports(userId, serviceReports);
//More methods that modify/update information
return zip(observable1, observable2, observable3
(report1, report2, report3) -> {
updateReports(otherArguments, report1, report2, report3);
return serviceReports;
});
});
}
So far I've tried;
#Test
public void myTest(){
when(serviceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
Observable<Reports> result = mocketClass.getUserReports(userId)
}
Tryed with Spy and Mock but no luck so far. Any hint or help would be great.
To mock getReports() behavior you need to mock the serviceClient firstly and pass it into your service class.
Just as example:
#Test
public void myTest(){
// Given
final ServiceClient mockedServiceClient = Mockito.mock(ServiceClient.class);
when(mockedServiceClient
.getReports(anyInt()))
.thenReturn(Observable.just(reports));
// and create an instance of your class under testing with injected mocked service client.
final MyUserService userService = new MyUserService();
userService.setServiceClient(mockedServiceClient);
// When run a method under test
Observable<Reports> actualResult = userService.getUserReports(userId)
// Then
// actualResult to be verified.
}

Resources