How to mock String extension? - kotlin

I'd like to mock a string extension.
I've read the instructions how this should be done, by using
mockStatic("kotlin.String")
or
mockkStatic("kotlin.kotlin_builtins")
but it keeps saying
Caused by: io.mockk.MockKException: Can't instantiate proxy for class kotlin.String
at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:64)
at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:29)
at io.mockk.impl.instantiation.AbstractMockFactory.spyk(AbstractMockFactory.kt:92)
at io.floriday.pdfgeneratorapi.integration.TradeItemListenerTest.<init>(TradeItemListenerTest.kt:131)
... 18 more
Caused by: io.mockk.proxy.MockKAgentException: Failed to create proxy for class java.lang.String.
class java.lang.String is one of excluded classes
at io.mockk.proxy.jvm.ProxyMaker.throwIfNotPossibleToProxy(ProxyMaker.kt:128)
at io.mockk.proxy.jvm.ProxyMaker.proxy(ProxyMaker.kt:28)
at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:34)
... 21 more
Probably I'm mocking the wrong file, but I can't seems to get the filename right to mock. Any help is appreciated :-D

It is a question to your extension function. Where it resides? There is no general approach to all extension functions.
I found a lot of String related functions in kotlin.text.StringsKt. How I found it? I just went to the definition(source codes) of one String extension functions in IDEA and found #JvmName annotation to know exact class name.
Please try following thing:
mockkStatic("kotlin.text.StringsKt") {
...
}
If this doesn't help you basically need to find out what class you need. Just comment what extension function you need.

Related

How can I tell the Kotlin compiler that a Java method will never return null?

I don't or can't modify the Java source code. The goal to configure just the Kotlin compiler to know what is nullable and what isn't.
You can specify the type manually if you know something will never be null. For example, if you have the following Java code:
public static Foo test() {
return null;
}
and you call it in Kotlin like this:
val result = Foo.test()
then result will have a type of Foo! by default – which means it can be either Foo or Foo?.. the compiler doesn't have enough information to determine that.
However, you can force the type manually:
val result: Foo = Foo.test()
// use "result" as a non-nullable type
Of course, if at runtime that is not true, you'll get a NullPointerException.
For reference, please check the documentation.
I don't know of a way to configure the compiler for this, but IntelliJ IDEA has a feature that allows you to add annotations to code via an XML file called external annotations.
You can add the Jetbrains #Nullable and #NotNull annotations to library code, but when I've tried it, it only results in compiler warnings rather than errors when you use incorrect nullability in your code. These same annotations generate compiler errors when used directly in the source code. I don't know why there is a difference in behavior.
You can use extension functions for this. If you have a method String foo() in the class Test, you can define the extension function
fun Test.safeFoo(): String = this.foo()!!
The advantage is that the code is pretty obious.
The disadvantage of this approach is that you need to write a lot of boiler plate code. You also have to define the extension function in a place where all your modules or projects can see it. Also, writing that much code just to avoid !! feels like overkill.
It should also be possible to write a Kotlin compiler extension which generates them for you but the extension would need to know which methods never return null.

How to make a class that inherits the same methods as IO::Path?

I want to build a class in Raku. Here's what I have so far:
unit class Vimwiki::File;
has Str:D $.path is required where *.IO.e;
method size {
return $.file.IO.s;
}
I'd like to get rid of the size method by simply making my class inherit the methods from IO::Path but I'm at a bit of a loss for how to accomplish this. Trying is IO::Path throws errors when I try to create a new object:
$vwf = Vimwiki::File.new(path => 't/test_file.md');
Must specify a non-empty string as a path
in block <unit> at t/01-basic.rakutest line 24
Must specify a non-empty string as a path
I always try a person's code when looking at someone's SO. Yours didn't work. (No declaration of $vwf.) That instantly alerts me that someone hasn't applied Minimal Reproducible Example principles.
So I did and less than 60 seconds later:
IO::Path.new
Yields the same error.
Why?
The doc for IO::Path.new shows its signature:
multi method new(Str:D $path, ...
So, IO::Path's new method expects a positional argument that's a Str. You (and my MRE) haven't passed a positional argument that's a Str. Thus the error message.
Of course, you've declared your own attribute $path, and have passed a named argument to set it, and that's unfortunately confused you because of the coincidence with the name path, but that's the fun of programming.
What next, take #1
Having a path attribute that duplicates IO::Path's strikes me as likely to lead to unnecessary complexity and/or bugs. So I think I'd nix that.
If all you're trying to do is wrap an additional check around the filename, then you could just write:
unit class Vimwiki::File is IO::Path;
method new ($path, |) { $path.IO.e ?? (callsame) !! die 'nope' }
callsame redispatches the ongoing routine call (the new method call), with the exact same arguments, to the next best fitting candidate(s) that would have been chosen if your new one containing the callsame hadn't been called. In this case, the next candidate(s) will be the existing new method(s) of IO::Path.
That seems fine to get started. Then you can add other attributes and methods as you see fit...
What next, take #2
...except for the IO::Path bug you filed, which means you can't initialize attributes in the normal way because IO::Path breaks the standard object construction protocol! :(
Liz shows one way to workaround this bug.
In an earlier version of this answer, I had not only showed but recommended another approach, namely delegation via handles instead of ordinary inheritance. I have since concluded that that was over-complicating things, and so removed it from this answer. And then I read your issue!
So I guess the delegation approach might still be appropriate as a workaround for a bug. So if later readers want to see it in action, follow #sdondley's link to their code. But I'm leaving it out of this (hopefully final! famous last words...) version of this answer in the hope that by the time you (later reader) read this, you just need to do something really simple like take #1.

How should I form a list property type with my own type

I am trying to form below final kotlin code
val participants: List<AbstractParty>
I tried to use below code in kotlinpoet but it shows error, I think it is not correct, but don't know how should I fix it. Any one can help? Thanks.
PropertySpec.builder("participants", List<ClassName("AbstractParty">)
Depending on whether you have a reference to a class or if you need to create its name from Strings, you can do either this:
PropertySpec.builder("participants",
ParameterizedTypeName.get(List::class, AbstractParty::class)
).build()
Or this:
PropertySpec.builder("participants",
ParameterizedTypeName.get(
List::class.asClassName(),
ClassName("some.pckg.name", "AbstractParty"))
).build()
A hint to finding out these sorts of things: KotlinPoet has pretty extensive tests, you can find examples of almost anything in there.
You can use parameterizedBy() extension:
PropertySpec.builder(
"participants",
List::class.asClassName().parameterizedBy(ClassName("some.pckg.name", "AbstractParty")
).build()
https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/-parameterized-type-name/-companion/parameterized-by.html

How to properly cast this class for OCMockito?

I'm using OCMockito to mock some objects in my tests.
When I use verify I receive an error from Xcode:
Multiple methods named '.....' found with mismatched result, parameter type or attributes
In the readme of the project i found this note:
(If Xcode complains about multiple methods with the same name, cast verify to the mocked class.)
This is my original implementation:
__strong Class mockAdjustClass = mockClass([Adjust class]);
[verify(mockAdjustClass) trackEvent:hasProperty(#"callbackParameters", hasEntry(#"duration", isNot(#"0")))];
I tried to cast in different ways but i cannot get rid of the error, for example:
[verify(([Adjust class])mockAdjustClass) trackEvent:hasProperty(#"callbackParameters", hasEntry(#"duration", isNot(#"0")))];
[([Adjust class])verify(mockAdjustClass) trackEvent:hasProperty(#"callbackParameters", hasEntry(#"duration", isNot(#"0")))];
I found the solution and was very easy :(
[(Adjust *)verify(mockAdjustClass) trackEvent:hasProperty(#"callbackParameters", hasEntry(#"duration", isNot(#"0")))];

System.Linq.Dynamic ´s .Where will be misinterpreted

I've build a large program with many references. F.e.:
System.Data.DataSetExtensions
System.Linq.Dynamic
I've to write a Dynamic Linq Expression:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
In my case:
Dim query As IEnumerable = ds.Sales.Where(strWhere)
But with System.Data.DataSetExtensions Where is misinterpreted. The compiler expects (Datarow, Integer, Boolean). If I delete System.Data.DataSetExtensions everything is ok with this expression, but I get many other errors, so I need this reference.
What can I do that the Where is interpreted correctly?
Is the large programm all in one file?
If not done already, split up your program into classes, then put each class into it's own file. Then only use the required references in every file.
Maybe this way you will be able to resolve the namespace conflict.
If for some reason you absolutely need both conflicting namespaces and can't resolve the ambiguity, you can directly call the extension method. Basically the extension method is just another static method on another class. ds.Sales.Where(strWhere) is only syntactic sugar for that method call.
An example:
ds.Sales.AsEnumerable().Where(yourCondition)
Would translate to
EnumerableRowCollectionExtensions.Where(ds.Sales.AsEnumerable(), yourCondition)