How do I specify that the collection parameter for a mocked method should have exactly one element - nmock

I am setting expectations for a method that takes a single IList<> parameter.
How do I express in NMock3 the following statement:
Method XX of the mock should be called exactly once with a list object that contains exactly one item.
The solution I imagine would be something like the following:
theMock.Expects.One.Method(_ =>_XX(null)).With(***mystery-mocking-goes-here***);

Use Is.Match:
theMock.Expects.One.Method(_ =>_XX(null)).With(Is.Match<IList<string>>(l => l.Count == 1));
Explanation for Anantha Raju C
If you have a method to test _XX(T). In the With method you have to pass a T object or a matcher. Is.Match create it and need a Predicate as argument.
In this example, the Predicate will return true if the list contains only one item (l.Count == 1).

Related

Default value in new method causing object construction to work in an unexpected way

Can someone help me understand the following behavior?
class Box {
has $.data;
multi method new($d) {
say 'here';
self.bless(data => $d);
}
}
# construct object with the custom new()
my $box = Box.new('hi');
say $box.data;
# construct object using default new()
my $box2 = Box.new(data => 'be');
say $box2.data;
This outputs:
here
hi
be
OK, perfect, exactly what is expected. However, change the code so the new method $d has a default value like this:
class Box {
has $.data;
multi method new($d = '') { # we give $d a default value now
say 'here';
self.bless(data => $d);
}
}
my $box = Box.new('hi');
say $box.data;
my $box2 = Box.new(data => 'be');
say $box2.data;
You now get this output:
here
hi
here # new method is getting called both times and $.data is not set
This is not what I expected. I figured I would get the same output as before. Can someone please explain why I don't get he same output?
UPDATE: I notice that if I change the new() signature to:
multi method new($d = '', *%_ ())
I can get things to work as expected. But I still don't understand exactly why it didn't work without *%_ () in the first place.
The two overloads of new under consideration here are yours and the one defined on the top-level type Mu. Namely,
multi method new($d)
multi method new(*%attrinit)
Or, written more explicitly,
multi method new(Box: $d?)
multi method new(Mu: *%attrinit)
But, we need to be even more explicit. Because, though it looks like only the latter should match Box.new(data => 'be'), the two are in fact both valid candidates. That's because, according to the documentation for Method,
Methods automatically capture extra named arguments into the special variable %_, where other types of Routine will throw at runtime. So
method x() {}
is actually equivalent to
method x(*%_) {}
and that applies to multi method as well. The rationale behind this is to allow methods to forward named arguments that they don't understand to their callers.
So, really, our two overloads are
multi method new(Box: $d?, *%_)
multi method new(Mu: *%attrinit)
So when we write Box.new(data => 'be'), we have two candidates which are valid, and the first one has a more specific invocant (Box rather than Mu), so it gets called.
In the case without the default argument, the candidates look like
multi method new(Box: $d, *%_)
multi method new(Mu: *%attrinit)
so the first multi is only a candidate for invocation if there's one positional argument.
We can use the trick from this Stack Overflow answer to suppress this behavior.
multi method new($d = '', *% ()) {
say "here $d";
self.bless(data => $d);
}
The *% () (the space is important here) is actually a rather neat little trick. The linked answer explains it better than I can, but basically the *% part says "I accept any named arguments", and then the () is a sub-signature to match against, namely the empty signature. You can't stop a method from accepting named arguments, so this more or less reads as "my method accepts any named arguments, as long as the list of named arguments is equal to the empty list".
Interesting question and good Answers already.
However, I think that both depend a little too much on obscure aspects of raku, namely 'bless' and '*% ()' - not to say that these tricks don't have a place, but that the common case given (a positional with default) should not need you to reach for the power tools.
Here's my solution:
class Box {
has $.data = ''; # we give data a default value here
multi method new($data) {
samewith(:$data) # redespatch positional data as named data
}
}

how to make then __index and __newindex detect table.index

I'm still a little newbie with metatables, and there is something that makes me confused
when I use metamethods like __index and __newindex in my metatable, they are only called when I invoke an element of the table as follows:
print(table[index]) -- this call the __index
table[index] = value -- this call the __newindex
but these two metamethods are not called when I invoke an element of the table as follows:
print(table.index) -- this does NOT call __index
table.index = value -- this does NOT call __newindex
my question is, is there any way to make table.index also call these two metamethods? or does only table[index] work?
Yes, __index will work with both brackets: mytable["index"] as well as the dot operator: mytable.index
mytable = setmetatable({}, { __index = function(t, k)
if k == "index" then
return "works fine"
end
return rawget(t, k)
end })
print(mytable["index"])
print(mytable.index)
You can circumvent the preset metatable methods using rawget and rawset
Having said that, if you are new to Lua I recommend looking for simple solutions that work WITHOUT metatables.
the __idnex and __newindex metamethods only get used when the table doesn't have an element at the index in question. If there's already an element, indexing will just return that element and setting it will just overwrite the existing element.
If you want complete control over all indices in a table, you have to keep it 100% empty and save all its values in another table and access those using the metamethods.

Inherit from table returned from function

There is an API provided function, let's call it createBase which returns a table (object). I want to add methods to this table, but I can't just do x = createBase() and then function x:foo() because I have another function similar to createBase, but it's createExtended. It might be easier to explain with the code I have so far:
import api --I don't know how you'd do this in vanilla Lua, I'd use os.loadAPI("api") but that's computercraft specific, I think
Extended = {}
function Extended:foo()
print("foo from extended")
end
function createExtended(params)
x = api.createBase(params)
Extended.__index = x
return Extended --this is obviously wrong: you can't return a class and expect it to be an object
end
Of course, this doesn't work: but I don't know how I might make it work either. Let's assume the table returned by createBase has a function called bar which just prints bar from base. With this test code, the following outputs are given:
e = createExtended()
e.foo() --prints "foo from extended"
e.bar() --nil, therefor error
How can I make this possible, short of defining function x.bar() inside createExtended?
Thanks in advance.
The very simplest way is to attach the method to it directly, instead of using a metatable.
local function extend(super_instance)
super_instance.newMethod = newMethod
return super_instance
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work, unless your superclass uses __newindex (for example, preventing you from writing to unknown properties/methods), or iterates over the keys using pairs or next, since it will now have an additional key.
If for some reason you cannot modify the object, you will instead have to 'wrap' it up.
You could make a new instance which "proxies" all of its methods, properties, and operators to another instance, except that it adds additional fields and methods.
local function extend(super_instance)
local extended_instance = {newMethod = newMethod}
-- and also `__add`, `__mul`, etc as needed
return setmetatable(extended_instance, {__index = super_instance, __newindex = super_instance})
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work for simple classes, but won't work for all uses:
Table iteration like pairs and next won't find the keys from the original table, since they're not actually there. If the superclass inspects the metatable of the object it is given (or if the superclass is actually a userdata), it will also not work, since you'll find the extension metatable instead.
However, many pure-Lua classes will not do those things, so this is still a fairly simple approach that will probably work for you.
You could also do something similar to Go; instead of having a way to 'extend' a class, you simply embed that class as a field and offer convenience to directly calling methods on the wrapping class that just call the methods on the 'extended' class.
This is slightly complicated by how 'methods' work in Lua. You can't tell if a property is a function-that-is-a-property or if it's actually a method. The code below assumes that all of the properties with type(v) == "function" are actually methods, which will usually be true, but may not actually be for your specific case.
In the worst case, you could just manually maintain the list of methods/properties you want to 'proxy', but depending on how many classes you need to proxy and how many properties they have, that could become unwieldy.
local function extend(super_instance)
return setmetatable({
newMethod = newMethod, -- also could be provided via a more complicated __index
}, {
__index = function(self, k)
-- Proxy everything but `newMethod` to `super_instance`.
local super_field = super_instance[k]
if type(super_field) == "function" then
-- Assume the access is for getting a method, since it's a function.
return function(self2, ...)
assert(self == self2) -- assume it's being called like a method
return super_field(super_instance, ...)
end
end
return super_field
end,
-- similar __newindex and __add, etc. if necessary
})
end
local function createExtended(...)
return extend(createSuper(...))
end

passing null as aparameter to listOf

can you please tell me what does the second parameter passed to the method listOf means? why do we need to pass null? why is the purpose of it?
code:
val listWithNulls: List<String?> = listOf("Kotlin", null)
listOf accepts a vararg of elements. Your second null is just one of many elements you passed to the list. Your list then consists of "Kotlin" and null.
So to answer your other questions:
why do we need to pass null? you don't need to...
what is the purpose of it? the person who wrote that code wanted to add a null element to the list... if it isn't clear from the context, why it is there, you should better ask the one who wrote that code. If it just consists of the line you showed, it's probably to demonstrate how lists with a nullable type can be constructed/used.

Getting a method parameters in Smalltalk

How to print the parameters of a specific method?
Parameters don't have types so you can't print those. It seems that you want to print the method header which provides the name of the method and the names of the parameters. You already have the name of the method so you need to get the names of the parameters. The only way to get the names of the parameters is from the original source string. Here's a nice way to extract the parameter names from the source string. In this example, I'm getting the name of the parameter of the printOn: method in class Object.
(Parser new parse: (Object sourceCodeAt: #printOn:) class: Object) arguments
collect: [:each | each name]
In Pharo3 it is even easier:
(Object>>#printOn:) argumentNames