i am trying to mock an object that has a function with multiple argument.
I would just try to set the expectation for it. That is, somehting of the form:
(item.addMetadata(,,,,,)).expects("","","","","","","")
I just don't know how to write it. The example, usually deal with one argument function: (item.addMetadata _).expects("")
How to deal with multiple argument ?
EDIT1
I change to Just for the sake of compiling:
(item.addMetadata _) expects (where {
(schema: String, element: String, qualifier: String, lang: String, value: String) => true
})
Now The problem apparently is that the method is overloaded ?
I get the following error:
Error:(21, 15) ambiguous reference to overloaded definition,
both method addMetadata in class Item of type (x$1: String, x$2: String, x$3: String, x$4: String, x$5: String, x$6: String, x$7: Int)Unit
and method addMetadata in class Item of type (x$1: String, x$2: String, x$3: String, x$4: String, x$5: String)Unit
match expected type ?
(item.addMetadata _) expects (where {
^
as a side not i should also added the fact that i am mocking a class and not an interface. This is class which is not under my control, has a private constructor and only a static create method. So i also get the following error:
Error:(18, 24) constructor Item in class Item cannot be accessed in <$anon: org.dspace.content.Item>
val item = mock[Item]
^
What i needed was to deal with an overloaded method of an object. I did not figure that out initially.
So the solution is to write:
(item.addMetadata(_: String, _:String, _:String, _:String, _:String)) expects ("hi", "he", "hey", "test", "holla")
Not sure however what would have been necessary if it was not an overloaded method, which was part of my original question.
(item.addMetadata _).expects(Seq("", "", "", "", "", "", ""))
See: http://scalamock.org/user-guide/advanced_topics/#example-5---repeated-parameters
Related
val (_,time) = time { Thread.sleep(1000) }
I see the Left Hand Side (LHS) has a val, so its declaring a variable. LHS also has some kind of a function syntax which does not look like a lambda declaration. What is (_,time)? Don’t you have to give a type to the time on the LHS? I understand the RHS perfectly well: it is a function which accepts a lambda as parameter and is named ‘time’. Original code
The left hand side is called destructuring.
If you try to assign an instance of a data class (or any class which has componentN functions) to a variable you can desturcture it. This means that you can assign its internals to variables. The _ syntax indicates that you don't care about the first item.
Example:
class Foo(val first: String, val second: String) {
operator fun component1() = first
operator fun component2() = second
}
Usage:
val (first, second) = Foo("first", "second")
If you use data classes you don't need to create the componentN functions, they are generated for you.
Equivalent data class:
data class Foo(val first: String, val second: String)
I am struggling with calling a function defined and implemented in a different package to my main file. This here is a replica of the structure of the codebase I am working on.
in repo/collegeutil/handlecourse.go
, I have
package collegeutil
func (clg *CollegeUtil) AddCourse(ctc context.Context, param1 string, param2 string) {
#Function implementation
}
CollegeUtil is a struct defined in repo/collegeutil/student.go. In this file, I have
package collegeutil
type CollegeUtil struct {
subSvc college.subjectService
}
And in a different file, that is in repo/college/student.go, I have
package college
type subjectService interface {
AddCourse(ctx context.Context, param1 string, param2 string)
}
Now in my repo/classes/main.go, I have the following
package main
reply, err := college.subjectService.AddCourse(ctx, param1 string, param2 string)
But this is not working. I’m getting an error that says too few arguments to call to college.subjectService.AddCourse. But the number of arguments is correct. Apparently it requires one more parameter in the beginning which is of college.subjectService value in argument. What is this actually? ?
I also tried collegeutil.CollegeUtil.AddCourse(). But here I get “can not call pointer method AddCourse on collegeutil.CollegeUtil”
What is the correct way of calling AddCourse method to the main in the above codebase?
I could see a few unexported items in your code sample. Try exporting them first and build..
Export subSvc:
package collegeutil
type CollegeUtil struct {
SubSvc college.subjectService
}
Eport subjectService:
package college
type SubjectService interface {
AddCourse(ctx context.Context, param1 string, param2 string)
}
And:
reply, err := college.SubjectService.AddCourse(ctx, param1 string, param2 string)
This is not a solution; since I don't have rough reputation to comment, adding here.
I have this class that takes a a varargs parameter and a key in the primary constructor, and a secondary constructor that only requires the key, then, when calling the primary constructor,
I just pass an empty Array and spread it *emptyArray<String>.
class AppendableParameter(val key: String, vararg parameters: String) {
constructor(key: String) : this(key, *emptyArray<String>())
}
The code works fine, but IntelliJ gives me a warning:
Remove redundant spread operator
If i do remove it though, it will not work as it'd be expecting a String, and the "suggested fix"
from IntelliJ just deletes the parameter, making the constructor call invalid.
Is this possibly a bug in IntelliJ's system, or am I missing something trivial?
I can't speak to the warning emitted by IntelliJ, but your secondary constructor is unnecessary. It's possible to call methods with a varargs parameter without passing any arguments for said varargs parameter, which is the same as passing an empty array. In other words, having:
class Foo(val key: String, vararg params: String)
Already let's you call the primary constructor like so:
val foo = Foo("key")
If you want a non-empty array to be used when no argument is given then you can specify a default argument:
class Foo(
val key: String,
vararg params: String = arrayOf("default", "params")
)
I am a Java programmer and new to Kotlin. Please help me understand the below code, especially the first line.
class SiteListEventBus : EventBus<SiteListEventBus.SiteListChangeEvent, String, NotificationHandler<SiteListEventBus.SiteListChangeEvent>>() {
data class SiteListChangeEvent(val entityId: String, val routingKey: String)
override fun getSubscriptionKey(event: SiteListChangeEvent?): String {
return event!!.routingKey
}
}
class SiteListEventBus :EventBus<SiteListEventBus.SiteListChangeEvent, String,
NotificationHandler<SiteListEventBus.SiteListChangeEvent>>() {
So from what im gathering here EventBus would be like your base class which SiteListEventBus is inheriting from and EventBus which conforms to or includes 3 type parameters
Which are SiteListEventBus.SiteListChangeEvent as type 1,
String as type 2,
then NotificationHandler as type 3 which then has a type parameter of SiteListEventBus.SiteListChangeEvent little complicated there
data class SiteListChangeEvent(val entityId: String, val routingKey: String)
This data class then would just be the parameters/variables SiteListChangeEvent which would be your entityId of type string and your routingKey of type string
override fun getSubscriptionKey(event: SiteListChangeEvent?): String {
return event!!.routingKey
}
this last method overrides your getter for subscription key passes in your event which is SiteListChangeEvent? which is an optional value from the ? (so this can be null) to be used and its expecting a String for a return type
then your returning your passed in event!!.routingKey. the not-null assertion operator (!!) converts any value to a non-null type and throws an exception if the value is null.
So, you can write event!!, and this will return a non-null value of event (e.g., a String in your example) or throw a null pointer exception if event is null: soooo this seems like a bad idea because if event is null this will crash for sure
if you need further explanation let me know and ill go into further detail
Here is how I read the first line:
class SiteListEventBus
Define a new class.
: FooBar()
Extend the class FooBar using the empty constructor.
FooBar is actually EventBus<SiteListEventBus.SiteListChangeEvent, String, NotificationHandler<SiteListEventBus.SiteListChangeEvent>>
Generics apply here the way you would expect in Java.
class SiteListEventBus : FooBar() {
Begin implementing the SiteListEventBus class.
Here is how I read the rest:
data class SiteListChangeEvent(val entityId: String, val routingKey: String)
Create a data class.
override fun getSubscriptionKey
The override is similar to the #Override annotation. Override the method getSubscriptionKey.
event!!.routingKey
The event variable is nullable. I recommend reading about the !! operator.
Current version of MVVM Light has a helper function named Set in ObservableObject class that an inheriting ViewModel class can call to both change property value and raise change notification in one call. Together with the new NameOf operator, this makes the boilerplate code of properties much smaller.
The problem however is that the Set function is overloaded and out of the 3 overloads, the following 2 overloads make VB.NET angry:
Protected Function [Set](Of T)(propertyName As String, ByRef field As T, newValue As T) As Boolean
Protected Function [Set](Of T)(ByRef field As T, newValue As T, <CallerMemberName> Optional propertyName As String = Nothing) As Boolean
Now if you have a String type property, VB.NET cannot differentiate as to which overload we are calling.
Overload resolution failed because no accessible '[Set]' is most specific for these arguments:
'Protected Overloads Function [Set](Of String)(propertyName As String, ByRef field As String, newValue As String) As Boolean': Not most specific.
'Protected Overloads Function [Set](Of String)(ByRef field As String, newValue As String, [propertyName As String = Nothing]) As Boolean': Not most specific.
Note that C# can handle this situation easily, by using ref keyword. Also that even though the current situation is related to MVVM Light, the problem itself is generic. I have tried to use named parameters too, but that doesn't help either. Any hints on how this could be solved?
Here again after almost a year. I just found a little workaround that would work in most cases. Instead of calling one of the overloads mentioned in the question, use the third overload:
Protected Function [Set](Of T)(ByRef field As T, newValue As T, <CallerMemberName> Optional propertyName As String = Nothing) As Boolean
The third parameter of this overload is optional and if you skip it in the call, it will use CallerMemberName to assign it a value. Since Set is almost always called from within the property, this approach should work nicely. No other overload takes two parameters, so compiler can resolve it correctly.