How to mock a constructor with a spy? - kotlin

I am currently trying to test my Exposed Kotlin code. I have a table that follows the form
object Foo: Table() {
*parameters*
}
and a method that looks something like
fun addNewFoo(){
Foo.insert { ... }
}
I'm testing addNewFoo and I want to verify the insert occurred, ideally using something like
verify { FooSpy.insert { ... } }
How do I mock the Foo table to be a spy so I can verify the call occurred, or what other approach should I take to verify this method being called?

You can first mock your singleton Foo class using mockkObject() and then verify. Here is the code:
mockkObject(Foo) // mock the object
addNewFoo() // call function that we're testing
verify { Foo.insert(any()) } // verify

There is discussion of ways to go about it: https://github.com/JetBrains/Exposed/issues/317
There seems to be no real intended way for testing but making small test tables in a test data base is the closest you can get.

Related

mockk, clearAllMocks or unmockkAll

mockk 1.9.3
In the test noticed if did static mock in previous test, the next test will be using same mock.
Thought to do a reset at #After, but not sure which one to use clearAllMocks or unmockkAll.
in https://mockk.io/
unmockkAll unmocks object, static and constructor mocks
clearAllMocks clears regular, object, static and constructor mocks
but not clear what are the difference by unmocks and clears.
e.g.
#Test
fun test_1() {
mockkStatic(TextUtils::class)
every { TextUtils.isEmpty(param } returns true
//test
doSomeThingUsingTextUtils()
// verify
... ...
}
#Test
fun test_2() {
// in this test it does not want the mocked stub behavior
}
What it should use, clear or 'unmock`?
For me, understanding the difference between Clearing and Unmocking was sufficient.
clear - deletes internal state of objects associated with mock
resulting in empty object
unmock - re-assigns transformation of
classes back to original state prior to mock
(Source)
PS: I understand the confusion! I had it as well!
Let me know if you have any questions. Thanks.

mockk, what is just run

Could not find explanation about the "just run", what does it mean when stub a function with it?
Will it make the mock object to call its real function, or make the function run a stub which does nothing?
Is there sample for showing some real use case?
#Test
fun `mocking functions that return Unit`() {
val SingletonObject = mockkObject<SingletonObject>()
every { SingletonObject.functionReturnNothing() } just Runs. // ???
SingletonObject.otherMemberFunction(). //which internally calls functionReturnNothing()
//...
}
with or without this every { SingletonObject.functionReturnNothing() } just Runs stub, the test is doing same.
Copy of the answer from #Raibaz:
just runs is used for methods returning Unit (i.e., not returning a value) on strict mocks.
If you create a mock that is not relaxed and invoke a method on it
that has not being stubbed with an every block, MockK will throw an exception.
To stub a method returning Unit, you can do
every { myObject.myMethod() } just runs
No, it doesn't (like mockito's .thenCallRealMethod()) :)
It "just runs", meaning it does not do anything.
To run the real method you can use:
every { ... } answers { callOriginal() }

Testing private methods in Raku

Is there a way to test private methods in Raku?
I understand that one should ideally define their tests targeting the public methods, but is there a way to do it "the wrong way"? :)
I initially thought about defining a subclass for the Testing that inherited from the class I wanted to test and do the tests there, but it seems that private methods are not inherited.
Then I saw the 'trusts' routine, but I wouldn't want to reference a Testing class on any of the classes of the code.
Is there something like changing the 'private' property of a method via introspection?
What would be the best way to call/test a private method?
This can be done using introspection.
Consider this is the class you want to test:
class SomeClass {
has Int $!attribute;
method set-value(Int $value) returns Nil {
$!attribute = $value;
return;
}
method get-value returns Int {
return $!attribute;
}
# Private method
method !increase-value-by(Int $extra) returns Nil {
$!attribute += $extra;
return;
}
}
You may create a test like this:
use Test;
use SomeClass;
plan 3;
my SomeClass $some-class = SomeClass.new;
my Method:D $increase-value = $some-class.^find_private_method: 'increase-value-by';
$some-class.set-value: 1;
$increase-value($some-class, 4);
is $some-class.get-value, 5, '1+4 = 5';
$increase-value($some-class, 5);
is $some-class.get-value, 10, '5+5 = 10';
my SomeClass $a-new-class = SomeClass.new;
$a-new-class.set-value: 0;
$increase-value($a-new-class, -1);
is $a-new-class.get-value, -1, '0+(-1) = -1; The method can be used on a new class';
done-testing;
You first create an instance of the class and the use ^find_private_method to get its private Method. Then you can call that Method by passing an instance of a class as the first parameter.
There's a more complete explanation on this answer:
How do you access private methods or attributes from outside the type they belong to?
A fresh cup of tea and #Julio's and #JJ's answers inspired the following:
class SomeClass { method !private ($foo) { say $foo } }
use MONKEY-TYPING; augment class SomeClass { trusts GLOBAL }
my SomeClass $some-class = SomeClass.new;
$some-class!SomeClass::private(42); # 42
My solution tweaks the class using monkey typing. Monkey typing is a generally dodgy thing to do (hence the LOUD pragma). But it seems tailor made for a case just like this. Augment the class with a trusts GLOBAL and Bob's your Uncle.
Raku requires the SomeClass:: qualification for this to work. (Perhaps when RakuAST macros arrive there'll be a tidy way to get around that.) My inclination is to think that having to write a class qualification is OK, and the above solution is much better than the following, but YMMV...
Perhaps, instead:
use MONKEY-TYPING;
augment class SomeClass {
multi method FALLBACK ($name where .starts-with('!!!'), |args) {
.(self, |args) with $?CLASS.^find_private_method: $name.substr: 3
}
}
and then:
$some-class.'!!!private'(42); # 42
I've used:
A multi for the FALLBACK, and have required that the method name string starts with !!!;
A regular method call (. not !);
Calling the method by a string version of its name.
The multi and !!! is in case the class being tested already has one or more FALLBACK methods declared.
A convention of prepending !!! seems more or less guaranteed to ensure that the testing code will never interfere with how the class is supposed to work. (In particular, if there were some call to a private method that didn't exist, and there was existing FALLBACK handling, it would handle that case without this monkey FALLBACK getting involved.)
It should also alert anyone reading the test code that something odd is going on, in the incredibly unlikely case that something weird did start happening, either because I'm missing something that I just can't see, or because some FALLBACK code within a class just so happened to use the same convention.
Besides using introspection, you can try and use a external helper role to access all private methods and call them directly. For instance:
role Privateer {
method test-private-method ( $method-name, |c ) {
self!"$method-name"(|c);
}
}
class Privateed does Privateer {
method !private() { return "⌣" }
}
my $obj = Privateed.new;
say $obj.test-private-method( "private" );
The key here is to call a method by name, which you can do with public and private methods, although for private methods you need to use their special syntax self!.

How can I write test cases as classes in dojo

I want to be able to write testcases as class hierarchies in dojo/doh.
But when the tests get called they seem to be called using hitch hence looses the inherited methods.
So far I've only been able to write test cases which are independant functions, but i'd like to refractor some of the common setup into a separate method
There might be a better way, but I just did this by declaring a BaseTest class that contains an array of test objects.
Example:
baseFieldViewTests: [{
name: "Test input widget()",
runTest: function () {
var inputWidget = this.field.getInputWidget();
doh.assertTrue(inputWidget.get, "Input widget has no get method");
doh.assertTrue(inputWidget.set, "Input widget has no set method");
doh.assertTrue(inputWidget.placeAt, "Input widget has no placeAt method");
}
},
Then in the subclass test I iterate through the base class tests and register them:
/**
* Register base field view tests
*/
baseFieldViewTests = new BaseFieldViewTest().baseFieldViewTests;
for (test in baseFieldViewTests) {
if (baseFieldViewTests[test]) {
doh.register("component/form/text/ReadOnlyTextViewTest",
{
name: baseFieldViewTests[test].name,
setUp: setUp,
runTest: baseFieldViewTests[test].runTest,
tearDown: tearDown
});
}
}
Not too elegant but it seems to work.

Too few interactions in a Spock test for a Grails service

I thought I've understood Spock interactions but I have to admin that I'm still missing some pieces of the picture.
Alright, here my problem: I have a method in a Grails service which performs some operations, including a call to a void method of the same service class. Here's the code:
class myService {
void myStuff(def myObj, params) {
// do my stuff
anotherMethod(myObj)
//do my stuff again
}
void anotherMethod(myObj) {
// do other stuff
}
}
I want to be sure that myStuff method calls anotherMethod, to test and document the correct behaviour.
So, here's the test in my Spock Specification class:
void 'test myStuff method'() {
given: 'my object and some params'
// doesn't really matter what I'm doing here
MyObject myObj = new MyObject()
params = [title: 'my object']
when: 'we call myStuff()'
service.myStuff(myObj, params)
then: 'anotherMethod() is called exactly one times'
1 * service.anotherMethod(myObj)
}
}
The error I get is:
Too few invocations for:
1 * service.anotherMethod(myObj) (0 invocations)
What do you think? What's wrong?
As always, thanks in advance.
You are asking for a very special, and generally discouraged, form of mock called partial mocking where methods on the class under test are mocked. Spock supports this since 0.7, but you'll have to create a Spy() rather than a Mock(). Also note that you cannot mock private methods. For more information on spies, see the reference documentation.