Argument capturing on the insides of closures in Spock - unit-testing

I am trying to test a method that does an invocation with a closure, something like this:
def foo(Long param) {
AnObject.doSomething {
bar(param)
}
}
And I want to test that doSomething is called with a closure that calls bar with the expected value inside.
I'm able to test properly the doSomething invocation by creating a spy and doing
when:
service.foo(1L)
then:
1 * AnObject.doSomething{_}
However, I cannot seem to find a way to perform assertions on the contents of the closure.
What's the appropriate way to assert that inside the closure bar gets called with 1L?

Without seeing more of your code, I think you would need to spy on the class providing the bar method. This is a bit contrived because the test is supplying the closure, but I think it is something like this:
import spock.lang.Specification
class Bar {
void bar(def param) {
println param
}
}
class DoSomethingTestSpec extends Specification {
class AnObject {
void doSomething(Closure c) {
def param = 1L
c.call(param)
}
}
def "test AnObject doSomething calls the closure"() {
given:
def closure = { def p ->
Bar.bar(p)
}
and:
GroovySpy(Bar, global:true)
and:
AnObject anObject = new AnObject()
when:
anObject.doSomething(closure)
then:
1 * Bar.bar(_) >> { args ->
assert args[0] == 1L
}
}
}

Related

Gmock function calls are not called

Gmock doesn't work as exected.
EXPECT_CALL doesn't call mock functions.
Here is the code snippet:
In Header.hpp:
typedef MockITest ITest;
Class mainclass
{
public:
std::shared_ptr<ITest> mTestCtrl;
funcToTest();
};
source.cpp
{
std::shared_ptr<mainclass> mainclassPtr;
funcToTest()
{
mTestCtrl = getCtrl();
if( nullptr != mTestCtrl){
cout<< "I can see print here";
mTestCtrl->start();
}
}
}
samplemock.h
class MockITest
{
public:
/// #brief function mock
MOCK_METHOD0(start, void());
};
std::shared_ptr<MockITest> getCtrl()
{
return std::make_shared<MockITest>();
}
test.cpp
TEST_F(TestMqttgwProcessKeepAlive, Test_funcToTest)
{
mainclassPtr = std::make_shared<mainclass>();
mainclassPtr->funcToTest();
EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start()).Times(1);
}
I get this error.
Uninteresting mock function call - returning directly.
Function call: start()
Actual function call count doesn't match EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start())...
Expected: to be called once
Actual: never called - unsatisfied and active
I think you should put EXPECT_CALL before the call to funcToTest:
TEST_F(TestMqttgwProcessKeepAlive, Test_funcToTest)
{
mainclassPtr = std::make_shared<mainclass>();
EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start()).Times(1);
mainclassPtr->funcToTest();
}
In general, expectations should come first, then calls to the functions that are expected to be called.

Mockito: Mock an invokable param

Kotlin function to test:
suspend fun <T: Any> handleSomething(call: suspend () -> Result<T>) {
if (call.invoke() == "Something") {
...
}
else {
...
}
}
I want to mock call here.
Usually I mock like:
val call = Mockito.mock(SomeClass::class.java)
But I don't know for param as function like this
Original answer: https://stackoverflow.com/a/53306974/11377112
This is how you mock a lambda function:
val call = Mockito.mock<suspend () -> Result<T>>()
handleSomething(call)
verify(call)()
// Or verify(call).invoke(any()) to be explicit

How to mock a method which passes in clazz?

I'm trying to write a unit test for a method which has takes in a .class parameter.
For example:
ExampleService {
def myExample(clazz){
//do stuff and return some object
}
}
/* How the above function gets used */
AnotherExampleService extends exampleService {
def blah() {
def obj = myExample(AnotherClass.class)
}
}
/* Now I need to test the above blah() function */
AnotherExampleServiceSpec extends Specification {
def "test blah"() {
//The following doesn't seem to work
ExampleService.metaClass.myExample = { def arg1 -> obj }
}
}
I'm pretty new to Groovy/Grails, so any help would be much appreciated. I basically want to know why my unit test doesn't seem to work, and how to test such a function that takes in a paramter of a class instance.
Thank you for your help!
I would probably subclass the ExampleService in the test. So it looked like:
ExampleService {
def myExample(clazz){
//do stuff and return some object
}
}
AnotherExampleService extends ExampleService {
def exampleService
def blah() {
def obj = myExample(AnotherClass)
}
}
AnotherExampleServiceSpec extends Specification {
def "test blah"() {
given:
AnotherExampleService service = new AnotherExampleService() {
#Override
def myExample(clazz){
//whatever you want to do
return whatEverResult
}
when:
def result = service.blah (SomeClass)
then:
result
}
}
As you can see the myExample methods is overridden here to return some mock value and there's no tinkering with metaclass :-) To make it easier for Groovy you can explicitly state the input type e.g. def myExample(Class clazz).

How to use Google Test to test a function which will call another function containing output parameters?

// Filter.h/cpp
class Filter
{
public:
int readInt(int* value)
{
if (value == NULL)
return 0;
*value = 15; // some logical;
return 1;
}
};
// TestTee.h/.cpp
class TestTee
{
public:
Func1(Filter* f)
{
...
int val;
f->readInt(&val);
...
}
}
Now, I need to test TestTee class, so I mock the class Filter
class MockFilter : public Filter
{
public:
MOCK_METHOD1(readInt, int(int*));
};
how to write the test case?
TEST_F(TestClass, Test1)
{
TestTee t;
MockFilter filter;
EXPECT_CALL(filter, readInt(_)).Times(1); // failed error: The mock function has no default action set, and its return type has no default value set." thrown in the test body.
/*
int val;
EXPECT_CALL(filter, readInt(&val)).Times(1);
Failed with the following error:
Expected: to be called once
Actual: never called - unsatisfied and active
*/
t.Func1(&filter);
}
So, my problem is
I don't know how to control the output parameters of a function which will be called in my testee function code.
Any comment? thx a lot.
First of all, don't forget that a function needs to be virtual for GoogleMock to be able to actually mock it:
class Filter
{
public:
virtual int readInt(int* value)
{
if (value == NULL)
return 0;
*value = 15; // some logical;
return 1;
}
};
The testing code depends on what you actually want to test. If you want just to ensure that Filter::readInt is called this should be enough:
TEST_F(TestClass, Test1)
{
TestTee t;
MockFilter filter;
EXPECT_CALL(filter, readInt(_));
t.Func1(&filter);
}
(Since readInt has built-in return type (int) GoogleMock should be able to figure out default return value without complaining)
If you want to ensure that readInt is called for example only once, use Times clause:
EXPECT_CALL(filter, readInt(_)).Times(1);
If you want the code of Testee following the readInt call to get adequate return values during test, i.e. if you want a mock to imitate returning values of real function, use Return clause for return value, and SetArgPointee clause for output value passed by pointer, or both like this:
EXPECT_CALL(filter, readInt(_)).WillOnce(DoAll(SetArgPointee<0>(15), Return(1)));

groovy regex test failing

In my Grails 1.3.6 app I've written this class
import org.apache.commons.lang.StringUtils
/**
* Implementation that converts a name such as <tt>FOO_BAR</tt> to <tt>fooBar</tt>
*/
#Singleton
class CamelCaseEnumTransformer implements EnumTransformer {
String transformName(Enum e) {
String transformedName = e.name().toLowerCase()
transformedName.replaceAll(/_([a-z])/) {
it[1].toUpperCase()
}
StringUtils.remove(transformedName, '_')
}
}
I've created this test case:
class EnumTransformerTests extends GroovyTestCase {
private static enum TestEnum {
A, FOO, FOO_BAR, FOO_BAR_123,
}
void testCamelCaseTransformer() {
EnumTransformer transformer = CamelCaseEnumTransformer.instance
assertEquals 'a', transformer.transformName(TestEnum.A)
assertEquals 'foo', transformer.transformName(TestEnum.FOO)
// This test fails on the line below
assertEquals 'fooBar', transformer.transformName(TestEnum.FOO_BAR)
}
}
The test fails on the line marked above. I reckon the problem must be related to the replaceAll method, because this is the first time that the closure passed as the second argument to this method is executed.
The error I get is:
groovy.lang.MissingMethodException: No signature of method:
CamelCaseEnumTransformer$_transformName_closure1.doCall()
is applicable for argument types: (java.lang.String, java.lang.String) values: [_b, b]
What's particularly strange, is that if I run the equivalent code below in the Groovy console, everything seems to work fine.
#Singleton
class CamelCaseEnumTransformer {
String transformName(Enum e) {
String transformedName = e.name().toLowerCase()
transformedName.replaceAll(/_([a-z])/) {
it[1].toUpperCase()
}
}
}
enum TestEnum {
A, FOO, FOO_BAR, FOO_BAR_123,
}
def transformer = CamelCaseEnumTransformer.instance
assert 'fooBar' == transformer.transformName(TestEnum.FOO_BAR)
From the error message text, it looks like the closure should accept 2 arguments for the 2 matches in your regex. Try the following:
transformedName.replaceAll(/_([a-z])/) { wholeMatch, capturedGroups ->
capturedGroups[0].toUpperCase();
}