I have a private method which was mocked in grails 1.3.7 using metaclass but now that I upgraded grails version to 2.2.4, the same mocking fails.
Method to test has a call to private method
private def MyPrivateMeth1(def arg1, def arg2) {
...
}
Mocking is something like this
MyController.metaClass.private.MyPrivateMeth1 = { a, b ->
...
}
Try using the #TestFor annotation, which will give you a controller variable. You can then alter the metaclass of that, as well as incorporating Kamil Mikolajczyk and araxn1d's suggestions. So, your whole test should probably look like this:
#TestFor(MyController)
class MyControllerTests {
setup() {
controller.metaClass.MyPrivateMeth1 = {def arg1, def arg2 ->
//you can make your mocked method return whatever you wish here
return [key1: "foo", key2: "bar"]
}
}
void testForSomething() {
//Some code here that invokes an action or two in your controller which in turn invokes the private method
}
}
Make sure to have def (or String, Long, or whatever declaration you use) on the arguments of your mock method precisely as they are on the actual private method in the controller, or your test will try to use the class's normal private method first.
Here's a similar test in Spock:
import spock.lang.Specification
import spock.lang.Unroll
import grails.test.mixin.*
import org.junit.*
#TestFor(MyController)
class MyControllerSpec {
def "test that thing"() {
setup:
controller.metaClass.MyPrivateMeth1 = {def arg1, def arg2 -> return someOutput }
expect:
controller.someAction() == expectedRender
where:
someOutput | expectedRender
[key1: "foo", key2: "bar"] | "expected render from controller"
}
}
It seems that you need to declare types of closure arguments (its 100% if that arguments have actual types, for example Long, but not sure about def, but you need to try):
MyController.metaClass.MyPrivateMeth1 = { def a, def b -> ... }
I believe you don't need the .private. part
MyController.metaClass.MyPrivateMeth1 = { a, b -> ... }
should be enough, however I would specify parameter types explicitly
And, by the way, you should keep java naming conventions - methods names should start with lowercase character
For unit tests I have used Reflection for private methods. Something similar to this should work...
Method method = BehaviourService.getDeclaredMethod("behaviourValidConstraints",User.class,Behaviour.class)
method.setAccessible(true)
boolean valid = ((Boolean)method.invoke(service, user,b)).booleanValue()
First you get the method with getDeclaredMethod setting the name and the parameter types, you set it accesible and finally tou call it with method.invoke passing the object that has the method and the parameters. The result is an Object so you have to cast it.
I know there must be a better solution, but this one is the only one I've found that works
Edit: Sorry, what's above is for making a call to a private method.
I think that I've mocked a private method before just doing...
MyController.metaClass.myPrivateMeth1 { a, b ->
...
}
Just like you wrote it but without the .private and the = sign. Also, as Kamil said, you should follow java naming conventions for method names...
Related
We are in process of writing Unit test cases using Spock, I am not able to understand the following code snippet in then section varifying the declaration,
then:
1 * service.fraudMigrationOnboardingService.onboard(_) >>
{merchantId -> successCallBack.call(response)}
what is the meaning of the above code.
Because your question is lacking detail, I have to speculate and make an educated guess about your test. :-/
So you have a service with a member or getter fraudMigrationOnboardingService.
fraudMigrationOnboardingService has a method onboard taking a single parameter.
Obviously fraudMigrationOnboardingService is a mock or spy, which is why you can check interactions like 1 * ... on it.
The developer who wrote this test and whom, as it seems, you are too shy to ask about its meaning or who has left your company, wanted something specific to happen when method onboard(_) is called (probably by service) during the test: a call-back method call. Thus she declared the method stub { merchantId -> successCallBack.call(response) } as a replacement for what onboard(_) would normally do in this case. In a spy it would execute the original method, in a mock it would no nothing at all. But obviously that is not the desired behaviour, maybe because the test relies on different behavious later on.
In general, I think a test which is hard to read should be refactored, but anyway, here I am replicating your situation:
package de.scrum_master.stackoverflow
import spock.lang.Specification
class DummyTest extends Specification {
static class Service {
FraudMigrationOnboardingService fraudMigrationOnboardingService
void doSomething(String name) {
println "Doing something"
fraudMigrationOnboardingService.onboard(name)
}
}
static class FraudMigrationOnboardingService {
void onboard(String name) {
println "On-boarding $name"
}
}
static class SuccessCallBack {
void call(int httpResponse) {
println "Callback HTTP response = $httpResponse"
}
}
def "Some service test"() {
given:
def onboardingService = Mock(FraudMigrationOnboardingService)
def service = new Service(fraudMigrationOnboardingService: onboardingService)
def successCallBack = new SuccessCallBack()
def response = 200
when:
service.doSomething("ACME Inc.")
then:
1 * service.fraudMigrationOnboardingService.onboard(_) >>
{ merchantId -> successCallBack.call(response) }
}
}
The console log says:
Doing something
Callback HTTP response = 200
If you would comment out >> { merchantId -> successCallBack.call(response) }, it would only print
Doing something
for a mock and if you also change the Mock(FraudMigrationOnboardingService) into a Spy(FraudMigrationOnboardingService) it would print
Doing something
On-boarding ACME Inc.
Update: Maybe you still don't understand what the closure means, I am not sure. So I will explain it a bit more: As I said, it is just a stub for the onboard(String) method. The method parameter is mapped to merchantId but not used in the stubbed method. Instead the callback is triggered.
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
Let's say that I have a mocked trait Foo:
trait Foo {
def op(x: String): Unit
}
and I mocked this interface using
val mockedFoo = mock[Foo]
I want the method op to throw an exception second time I call it, e.g.
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
trait Foo {
def op(x: String): Unit
}
class DummySpec extends Specification with Mockito {
"dummy" should {
"test" in {
val mockedFoo = mock[Foo]
org.mockito.Mockito.doNothing().doThrow(new RuntimeException).when(mockedFoo).op(any[String])
mockedFoo.op("This one should work fine") should not(throwAn[Exception])
mockedFoo.op("This one should throw an exception") should throwAn[Exception]
}
}
}
Is there a way to do this in specs2 style? e.g.
mockedFoo.op(any[String]) returns Unit thenThrows new RuntimeException
but this doesn't compile.
Thanks!
The Unit return type makes things a bit trickier as you can't just chain:
returns "foo" thenThrows new RuntimeException
But you can still solve this problem if you use answers like below:
mockedFoo.op(anyString) answers {args => } thenThrows new RuntimeException
See if this works for you.
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