How can you unit test a class that has a superclass in Spock that invokes method calls form its superclass? Or how do you mock a superclass in Spock?
Ex:
class Bar {
def method1(parm1){
//Method actions
}
}
class Foo extends Bar {
def method2(param1, param2) {
//Method actions
super.method1(param1)
}
}
How can I mock behavior of class Bar?
You might use your class Foo as a Spy. The spy will create an instance of your class Foo but gives you the possibility of mocking any public methods declared in your spies class hierarchy.
def fooInstance = Spy(Foo)
fooInstance.method1(_) >> 'return value'
The following code will help you to specify what methods are called actually.
setup:
def fooInstance = Spy(Foo)
when: "this try-catch block is debug code"
try {
// do something with Foo or Bar
}
catch (Exception e) {
}
then:
0 * fooInstance._
This site may be useful. -> Spock Mock Cheatsheet
If you are using Spock to test Kotlin classes, you need to make the superclass methods open so that Spock can stub them.
Related
I am writing an interaction based test with the Help of the Spock Framework, where I would like to check that a method calls another method once.
The class under test looks like this:
class ClassUnderTest {
def a() {
b()
}
def b() {}
}
And my test case looks like this
class ClassUnderTestTest extends Specification {
ClassUnderTest cut
ClassUnderTest spied
def setup() {
cut = new ClassUnderTest()
spied = Spy(cut)
}
def "Method a() calls method b()"() {
when:
spied.a()
then:
1 * spied.a()
1 * spied.b()
}
}
Running this test, Spock recognises only the call to a() but not the call to b().
What did I wrong or what did I miss?
Your code works, make sure you have a recent version of spock-core the current version is 2.0-groovy-3.0, you also need byte-buddy to mock classes instead of just interfaces.
I am trying to write unit test cases for a Kotlin class A and trying to mock return client() call present in test() method to unit test test() method:
A.kt kotlin class:
class A (par 1, par 2) : B(par 1, par 2) {
override fun test(item: String): Boolean {
return client()
}
}
B.kt kotlin class:
abstract class B(par 1, par 2) {
private val client: WebClient by lazy {
//does something
}
protected fun client(): WebClient = client
}
Is it possible to mock the client() call in test() method?
And if possible how to do it and what library should I use for mocking?
This should be doable using Mockito testing framework. However, mocking an object returned from a object's method would require mocking the object itself.
val mockOfA = Mockito.mock(A::class)
val mockOfClient = Mockito.mock(WebClient:class)
Mockito.when(mockOfA.test(anyString())).thenReturn(mockOfClient) // Mind your original snippet return type Boolean from A.test()
If your class A implements internal logic you want to test in your test scenario, there are two possible paths:
Create a Spy instead of a Mock. Mocks do only whatever you explicitly set them up to do. Spy 'falls back' to original implementation when it is not given any mock behaviour.
Rewrite you class A so that it depends on external dependency of a ClientProvider to get an instance of WebClient to return in method test() and inject a mock of said provider to your object of type A during the test.
Using Spock framework for java unit testing.
When unit testing a method method1() and method1 is calling a method method2(),In method2() having a code statement as below :
Config config = new Config();
TimeZone tz=TimeZone.getTimeZone(config.getProps().getProperty(Constants.SERVER_TIMEZONE));
The call config.getProps().getProperty(Constants.SERVER_TIMEZONE)
returns America/Cambridge_Bay
In getProps method the property files is fetched from weblogic domain and it will not be available in spcok, its taking path as null.
Please suggest how can this function call be mocked in spock.
We can use meta class injection to mock response method2 in unit testing given block. Here ClassName is the class to which method2 belongs to.
ClassName.metaClass.method2 = { inputParameters ->
return "America/Cambridge_Bay"
}
Also it is advisable to use #ConfineMetaClass([ClassName]) annotation on the unit test to confine the meta class injection changes to your test case.
Lets start with an example which simulates your situation:
class Config {
Properties getProps() {
def props = new Properties()
props.setProperty(Constants.SERVER_TIMEZONE, 'America/Cambridge_Bay')
props
}
}
class Constants {
static String SERVER_TIMEZONE = 'TIMEZONE'
}
Config config = new Config()
def timeZoneID = config.getProps().getProperty(Constants.SERVER_TIMEZONE)
def tz = TimeZone.getTimeZone(timeZoneID)
assert tz.ID == 'America/Cambridge_Bay'
Since method2() doesn't get a Config instance injected into it, mocks are out of the question. So we'll use Groovy's metaClass, at the class level (since instance level is out of the question too, for the same reason). You can override Config.getProps() like this:
Config.metaClass.getProps {
def props = new Properties()
props.setProperty(Constants.SERVER_TIMEZONE, 'Etc/UTC')
props
}
So you can write your Spock test roughly like this:
// import Constants
// import Config class
class FooSpec extends Specification {
#ConfineMetaClassChanges
def "test stuff"() {
when:
Config.metaClass.getProps {
def props = new Properties()
props.setProperty(Constants.SERVER_TIMEZONE, 'America/Cambridge_Bay')
props
}
// Do more stuff
then:
// Check results
}
}
PS
If you can modify method2() to have Config injected, that would be preferable since then you can use Groovy's MockFor.
Imagine I have the following class.
class SomeClass {
public function shortcutMethod($arg1) {
return $this->method($arg1, 'something');
}
public function method($arg1, $arg2) {
// some stuff
}
}
So the shortcutMethod is a shortcut to the other method. Let us say I want to write a test that given and $arg1 the shortcutMethod will correctly call method with the correct arguments.
So far I think I figured I need to mock the class to expect a call to method with some arguments and then call shortcutMethod on the mock object like so (note I am using Mockery).
$mock = m::mock("SomeClass");
$mock = $mock->shouldReceive('method')->times(1)->withArgs([
'foo',
'something'
]);
$mock->shortcutMethod('foo');
This results in an exception like so shortcutMethod() does not exist on this mock object.
Did I misunderstand the usage for mocking? I understand it makes more sense for objects that are dependency injected into the class, but what in this scenario? How would you go about it? And perhabs more importantly, is this sort of testing useless, and if so, why?
You should use mocking to mock out the dependencies of the class under test, not the class under test itself. After all, you are trying to test the real behavior of your class.
Your example is a little basic. How you would test such a class would depend on what your method function does. If it returns a value that is in turn returned by shortCutMethod then I would say that your should just be asserting the output of shortCutMethod. Any dependencies within the method function should be mocked (methods belonging to other classes). I'm not that familiar with mockery, but I've given a tweaked version of your example a go.
class SomeClass {
private $dependency;
public function __construct($mockedObject) {
$this->dependency = $mockedObject;
}
public function shortcutMethod($arg1) {
return $this->method($arg1, 'something');
}
public function method($arg1, $arg2) {
return $this->dependency->mockedMethod($arg1, $arg2);
}
}
$mock = m::mock("mockedClass");
$mock->shouldReceive('mockedMethod')->times(1)->withArgs([
'foo',
'something'
])->andReturn('returnedValue');
$testCase = new SomeClass($mock);
$this->assertEquals(
'returnedValue',
$testCase->shortcutMethod('foo')
);
Having said that, it is possible to partially mock your class under test so that you can test the real behavior of the shortCutMethod function but mock out the method function to assert that it is called with the expected arguments. Have a look at partial mocks.
http://docs.mockery.io/en/latest/reference/partial_mocks.html
First-timer here, apologies if I've missed anything.
I'm hoping to get around a call to a static method using Spock. Feedback would be great
With groovy mocks, I thought I'd be able to get past the static call but haven't found it.
For background, I'm in the process of retrofitting tests in legacy java. Refactoring is prohibited. I'm using spock-0.7 with groovy-1.8.
The call to the static method is chained with an instance call in this form:
public class ClassUnderTest{
public void methodUnderTest(Parameter param){
//everything else commented out
Thing someThing = ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(param);
}
}
staticMethod returns an instance of ClassWithStatic
instanceMethod returns the Thing needed in the rest of the method
If I directly exercise the global mock, it returns the mocked instance ok:
def exerciseTheStaticMock(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
when:
println(ClassWithStatic.staticMethodThatReturnsAnInstance().instanceMethod(testParam))
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
But if I run the methodUnderTest from the ClassUnderTest:
def failingAttemptToGetPastStatic(){
given:
def globalMock = GroovyMock(ClassWithStatic,global: true)
def instanceMock = Mock(ClassWithStatic)
ClassUnderTest myClassUnderTest = new ClassUnderTest()
when:
myClassUnderTest.methodUnderTest(testParam)
then:
interaction{
1 * ClassWithStatic.staticMethodThatReturnsAnInstance() >> instanceMock
1 * instanceMock.instanceMethod(_) >> returnThing
}
}
It throws down a real instance of ClassWithStatic that goes on to fail in its instanceMethod.
Spock can only mock static methods implemented in Groovy. For mocking static methods implemented in Java, you'll need to use a tool like GroovyMock , PowerMock or JMockit.
PS: Given that these tools pull of some deep tricks in order to achieve their goals, I'd be interested to hear if and how well they work together with tests implemented in Groovy/Spock (rather than Java/JUnit).
Here is how I solved my similar issue (mocking a static method call which is being called from another static class) with Spock (v1.0) and PowerMock (v1.6.4)
import org.junit.Rule
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.rule.PowerMockRule
import spock.lang.Specification
import static org.powermock.api.mockito.PowerMockito.mockStatic
import static org.powermock.api.mockito.PowerMockito.when
#PrepareForTest([YourStaticClass.class])
#PowerMockIgnore(["javax.xml.*", "ch.qos.logback.*", "org.slf4j.*"])
class YourSpockSpec extends Specification {
#Rule
Powermocked powermocked = new Powermocked();
def "something something something something"() {
mockStatic(YourStaticClass.class)
when: 'something something'
def mocked = Mock(YourClass)
mocked.someMethod(_) >> "return me"
when(YourStaticClass.someStaticMethod(xyz)).thenReturn(mocked)
then: 'expect something'
YourStaticClass.someStaticMethod(xyz).someMethod(abc) == "return me"
}
}
The #PowerMockIgnore annotation is optional, only use it if there is some conflicts with existing libraries
A workaround would be to wrap the static method call into an instance method.
class BeingTested {
public void methodA() {
...
// was:
// OtherClass.staticMethod();
// replaced with:
wrapperMethod();
...
}
// add a wrapper method for testing purpose
void wrapperMethod() {
OtherClass.staticMethod();
}
}
Now you can use a Spy to mock out the static method.
class BeingTestedSpec extends Specification {
#Subject BeingTested object = new BeingTested()
def "test static method"() {
given: "a spy into the object"
def spyObject = Spy(object)
when: "methodA is called"
spyObject.methodA()
then: "the static method wrapper is called"
1 * spyObject.wrapperMethod() >> {}
}
}
You can also stub in canned response for the wrapper method if it's supposed to return a value. This solution uses only Spock built-in functions and works with both Java and Groovy classes without any dependencies on PowerMock or GroovyMock.
The way I've gotten around static methods in Groovy/Spock is by creating proxy classes that are substituted out in the actual code. These proxy classes simply return the static method that you need. You would just pass in the proxy classes to the constructor of the class you're testing.
Thus, when you write your tests, you'd reach out to the proxy class (that will then return the static method) and you should be able to test that way.
I have recently found 'spock.mockfree' package, it helps mocking final classes and static classes/methods.
It is quite simple as with this framework, in this case, you would need only to Spy() the class under test and #MockStatic the static method you need.
Example:
We used a static method returnA of StaticMethodClass class
public class StaticMethodClass {
public static String returnA() {
return "A";
}
}
here is the calling code
public class CallStaticMethodClass {
public String useStatic() {
return StaticMethodClass.returnA();
}
}
Now we need to test the useStatic method of CallStaticMethodClass class But spock itself does not support mock static methods, and we support
class CallStaticMethodClassTest extends Specification {
def 'call static method is mocked method'() {
given:
CallStaticMethodClass callStaticMethodClass = Spy()
println("useStatic")
expect:
callStaticMethodClass.useStatic() == 'M'
}
#MockStatic(StaticMethodClass)
public static String returnA() {
return "M";
}
}
We use the #MockStatic annotation to mark which class needs to be mocked
Directly implement the static method that requires mocking under it, the method signature remains the same, but the implementation is different.
Link to the framework:
https://github.com/sayweee/spock-mockfree/blob/498e09dc95f841c4061fa8224fcaccfc53904c67/README.md