Mock method on a Mock Object in Spock - grails

I have the following class which i am trying to mock using spock:
final class A{
private B b
public getB(){
return b
}
public A(B b){
this.b = b
}
}
and I tried to mock this class using following code and it is working.
def "test"(){
def mockA = GroovyMock(A)
when:
service.x()
then:
1 * new A(*_) >> {mockA}
}
Below is my x() method:
x(){
A a = new A(b)
B b = a.getB()
}
Now I want to mock a.getB() to get a mock object for B. I tried to create a mock for B but I am getting null at a.getB(). Is it possible to mock the getB() method to get a mock Object for B?
So I want to do some thing like
1 * a.getB() >> {mockB}
but I am getting null exception

do
def mockA = GroovyMock(A) >> {
getB() >> GroovyMock(B)
}.
P.S. I am surprised mocking a constructor of A works without specifying global: true

Related

Can't able to create mock in inheritance relationship with spock

I am new to spock.I have created mock object in normal class its works fine. But when we have inheritance like structure as below then I can't able to mock the things properly its gives error (null pointer). Any one have idea how we can do it in spock.
Class Parent{
Third getThird(){
return third;
}
}
Class Child extend Parent{
Object method1(){
String msg=getThird().someMethod(); // need to mock this line
return object;
}
}
given:
Third third=Mock()
Child child=new Child()
child.getThird(false) >> third
third.someMethod() >> "xyz"
when :
Object object=child.method1()
then:
//comparing the things
Can you try this?:
given:
def third = Mock(Third)
Child.metaClass.getThird = {
third
}
when :
Object object=child.method1()
then:
1 * thirdMocked.someMethod() >> "xyz"
and:
//comparing the things
cleanup:
Child.metaClass = null
you can mock classes in Spock like any interfaces :
given:
def thirdMock = Mock(Third) {
someMethod() >> "xyz"
}
def child = Mock(Child) {
third >> thirdMock
}
when :
def object = child.method1()
then:
//comparing the things
however, it's usualy a symptom of a code not really testable. in your case, you should probably make 'third' injectable, and then inject a mock.

Spock - test fails after interaction testing

This test works only when condition is tested. When mixed with interaction testing, it fails.
class Test extends Specification {
class Inner {
public String greet() {
return "hello"
}
}
def "simple test"() {
given:
def inner = Mock(Inner)
inner.greet() >> { "hi" }
when:
def msg = inner.greet()
then:
1 * inner.greet() // Below will pass when this line commented out.
msg == "hi"
}
}
The test will pass when interaction testing is removed.
Condition not satisfied:
msg == "hi"
| |
| false
null
It should be:
#Grab('org.spockframework:spock-core:0.7-groovy-2.0')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
class Inner {
public String greet() {
return "hello"
}
}
def "simple test"() {
given:
def inner = Mock(Inner)
when:
def msg = inner.greet()
then:
1 * inner.greet() >> "hi"
msg == "hi"
}
}
Let's talk a bit about what's going on. (Or if you don't want to, read the "Scope of Interactions" section.)
What's happening is an issue of scoping. As you may know, you can have multiple sequential when/then pairs; any Mocking done in a then block is actually scoped to only its when block. What happens if the Mocked method was already defined outside the when/then scoping? The Mock defined in the then block takes precedence.
Congratulations! You've stumbled across the only way to overwrite established Mocked values/methods. I spent a long time figuring out how this worked before the new documentation was released.
So we know you're overwriting your mock that defines a value to return. How do we proceed from here?
given:
def inner = Mock(Inner)
1 * inner.greet() >> message
expect:
"hi" = inner.greet()
where:
message = "hi"
Parting thought... I hope you're not testing a value that you set within your test. That's effectively asserting 1 == 1. If you want to test your actual code while testing behavior I'd suggest using a Spy
given:
def inner = Spy(Inner)
1 * inner.greet() >> {
callRealMethod() // Actual method, read the documentation I linked
}
expect:
"hi" = inner.greet()

How do I set properties via map constructors in an inherited class in Grails?

class A {
String a
}
class B extends A {
String b
}
Now I want to set both properties via map construction when creating an instance of B
def instance = new B(a: "foo", b: "bar")
assert instance.b != null
Only it doesnt work.
Actually it does work in pure Groovy but it doesnt work with Grails domain objects in Spock tests.
The following test passes with Grails 2.3.8.
A super classs...
// grails-app/domain/inheritedproperties/SuperClass.groovy
package inheritedproperties
class SuperClass {
String a
}
A subclass...
// grails-app/domain/inheritedproperties/SubClass.groovy
package inheritedproperties
class SubClass extends SuperClass {
String b
}
A Spock spec...
// test/unit/inheritedproperties/SubClassSpec.groovy
package inheritedproperties
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(SubClass)
#Mock(SuperClass)
class SubClassSpec extends Specification {
void "test binding inherited properties"() {
when:
def instance = new SubClass(a: 'A', b: 'B')
then:
'A' == instance.a
'B' == instance.b
}
}

Override Getter in Controller

I don't appear to be able to override a getter within my grails controller. The sample code I've created to illustrate this is provided below:
class MyController extends RestfulController<MyDomainObj> {
def field
def getField(){
field += 1
}
def index(MyCommand command) {
field = 1
// in a controller this prints 1, but in my class it prints 2
println('field' + field)
}
}
If I create a Groovy class and override the getter then it works.
class X {
public static void main(String[] args){
def x = new X()
x.field = 1
println x.field
}
def field
def getField(){
field += 1
}
}
Am I doing something wrong in the Controller or is this feature not supported in controllers? If it isn't supported, then does anyone know why? What magic is going on that would cause this feature not to work?
For attributes within a class, Groovy uses the generated private variable directly:
See http://groovy.codehaus.org/Groovy+Beans:
If you access a property from within the class the property is defined
in at compile time with implicit or explicit this (for example
this.foo, or simply foo), Groovy will access the field directly
instead of going though the getter and setter.
Example:
class C {
def prop
def getProp() {
println "getter"
prop
}
def dostuff() {
prop = "Y"
println prop
println getProp()
}
}
new C().dostuff()
results in
Y
getter
Y

GORM bidirectional One-to-Many

I'm trying to create a bidirectional one-to-many relationship between Foo and Bar domains in GORM.
Here's what I have so far:
class Bar {
static belongsTo = [foo: Foo]
}
class Foo {
Set bars = []
static hasMany = [bars: Bar]
}
The problem that I'm having is when I go to use the relationship methods, they don't seem to behave the way that I think they should. For example, you would think a statement like "foo.bars.add(bar)" would also set the foo field on the bar argument. But when I call "bar.foo.id" I'm told that the foo field is null. I can fix that problem if I use "bar.foo = foo" instead of "foo.bars.add(bar)". Unfortunately, when I call "foo.bars.size()" it tells me that it is 0.
To get a clearer picture of what I'm talking about, here are my tests:
def testFoo() {
def foo = new Foo()
def bar = new Bar()
foo.bars.add(bar)
println "foo.bars.size() = ${foo.bars.size()}"
println "bar.id = ${bar.id}"
for(def xbar : foo.bars) {
println "bar.id = ${xbar.id}"
}
println "foo.id = ${foo.id}"
println "bar.foo.id = ${bar?.foo?.id}" // <- is null
}
def testBar() {
def foo = new Foo()
def bar = new Bar()
bar.foo = foo
println "foo.bars.size() = ${foo.bars.size()}" // <- is 0
println "bar.id = ${bar.id}"
for(def xbar : foo.bars) {
println "bar.id = ${xbar.id}"
}
println "foo.id = ${foo.id}"
println "bar.foo.id = ${bar?.foo?.id}"
}
What am I doing wrong?
Note: I'm running this through an integration test. I've also found that "foo.addToBars(bar)" works the way that I think "foo.bars.add(bar)" and "bar.foo = foo" should work.
Update Here's a quick hack I did that does what I want (using Hibernate and JPA):
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import stuff.Foo;
public class MyList<Bar> extends LinkedList {
private Foo foo;
public MyList(Foo foo) {
this.foo = foo;
}
#Override
public boolean add(Object obj) {
boolean result = super.add(obj);
try {
Method barMethod = obj.getClass().getDeclaredMethod("setFoo", Foo.class);
barMethod.invoke(obj, foo);
}
catch(NoSuchMethodException noSuchMethod) {
noSuchMethod.printStackTrace();
}
catch(InvocationTargetException invocationTarget) {
invocationTarget.printStackTrace();
}
catch(IllegalAccessException illegalAccess) {
illegalAccess.printStackTrace();
}
return result;
}
}
If you read the documentation, you'll learn that, as you found out but are still questioning, the correct way to add items to a collection so they are persisted correctly is to use the addTo* methods.
So in your case, when you said that using addToBars worked, that's the right way to do this. That said, there are some performance hits you take with that. Another way is to do:
bar.foo = foo
bar.save()
The downside is that foo will not contain bar in its existing Set. You'd have to pull it from the database again. It's a bit of a give and take and you just use the best method for your situation.

Resources