How do you mock a method in GroovyTestCase? - java

I've been trying to figure out stubbing and mocking through the groovy testing tutorial to no avail. I'm trying to stub (or mock, I'm not quite sure on the terminology) this method, however I can't figure out how to actually get the syntax right. I would appreciate some help. I'm using groovy 2.4.5
public class foo {
public static void main(String[] args){
method1();
}
public static void method1(){
//do stuff
Object baz = new Object();
method2(baz);
}
public static void method2(Object baz){
//do stuff
}
}
class FooTest extends groovy.util.GroovyTestCase {
void testMainLoop(){
def stubMethod2 = new StubFor(foo);
stubMethod2.ignore.method2
stubMethod2.use {
foo.method1();
}
}
}
This code throws the error:
groovy.lang.MissingPropertyException: No such property: method2 for class: groovy.mock.interceptor.Ignore
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
at org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:87)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
at fooTest.testMainLoop(fooTest.groovy:14)

You should rather use:
stubMethod2.ignore('method2')
than:
stubMethod2.ignore.method2
Could you please clarify what you want to achieve?
BTW: I suggest to use spock instead of groovy built-in testing.

Related

Java MockedStatic method is still called

So I'm using MockedStatic<> to mock a static method but it seems like the item inside is still getting called? If this is the case, what's the point of mocking it? I have the following setup:
Object being tested:
public class ObjectBeingTested {
public void methodBeingTested() {
Object obj = ObjectInQuestion.getInstance(new Object(), "abc");
// do stuff with obj
}
}
The object with static method:
public class ObjectInQuestion {
public static ObjectInQuestion getInstance(Object obj, String blah) {
someLocalVar = new FileRequiredObject();
// we get NullPointerException here cuz in test env, no files found
}
private ObjectInQuestion() {
// private constructor to make people use getInstance
}
}
Test code:
public class MyTestClass {
MockedStatic<SomeClass> mySomeClass;
#Mock ObjectInQuestion mMockedObjectInQuestion;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mySomeClass = mockStatic(SomeClass.class);
when(SomeClass.getInstance(any(), anyString()).thenReturn(mMockedObjectInQuestion);
}
#After
public void tearDown() {
mySomeClass.close();
}
}
My questions are the following:
Why calling ObjectInQuestion.getInstance() in the test class, it's totally fine but when it's being called from ObjectBeingTested, it runs the real construction?
I tried to use mockConstruction on FileRequiredObject, it still actually construct the object ... why?
You're using the wrong syntax for stubbing the static method. You want something like
mySomeClass.when(
()->SomeClass.getInstance(any(), anyString()))
.thenReturn(mMockedObjectInQuestion);
More information available here
Assuming MockedStatic<SomeClass> mySomeClass; is actually MockedStatic<ObjectInQuestion> mySomeClass;, I would try to simplify the setup using a classic try block.
In any case, sharing the actual test method might be able to shine some light. ;)

How to define a new method inside an existing class and add a call to it in an existing method inside the same class using bytebuddy?

I have a class which looks like below
public class HelloWorld{
public void sayHelloWorld(){
System.out.println("Hello World");
}
}
Now I would like to add another method to the HelloWorld class using bytebuddy and add a call to the new method in sayHelloWorld. So hypothetically the class would look like this after bytebuddy does it's magic. (I know that bytebuddy works with bytecode and not java source files. The below code is just for illustration purpose.)
public class HelloWorld{
public void sayHelloWorld(){
System.out.println("Hello World");
sayHelloAgain()
}
public void sayHelloAgain(){
System.out.println("Hello Again")
}
}
Firstly, is this possible with bytebuddy?
Secondly, if it is possible, how can I do it? I have understood that bytebuddy can be used to redefine methods, but not modify the method body. Is this true?
It would be great if someone could shed some light on this. TIA!
Byte Buddy allows you to do this in various ways. The most straight forward way would be to define an interceptor that implements sayHelloAgain to which Byte Buddy creates a delegation:
public class HelloAgainDelegate {
public static void sayHelloAgain() {
System.out.println("Hello again");
}
}
You can then define the method on the redefined class and rebase the sayHelloWorld method to first invoke the original method and then invoke the other method:
Class<?> type = new ByteBuddy()
.rebase(HelloWorld.class)
.defineMethod("sayHelloAgain", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(HelloAgainDelegate.class))
.method(named("sayHelloWorld"))
.intercept(SuperMethodCall.INSTANCE
.andThen(MethodCall.invoke(named("sayHelloAgain"))))
.make()
.load(HelloWorld.class.getClassLoader(),
ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
Object instance = type.newInstance();
type.getMethod("sayHelloWorld").invoke(instance);
type.getMethod("sayHelloAgain").invoke(instance);
In Java code, the rebased class would look something like this:
public class HelloWorld {
synthetic void sayHelloWorld$origin() {
System.out.println("Hello World");
}
public void sayHelloWorld() {
sayHelloWorld$origin();
sayHelloAgain();
}
public void sayHelloAgain() {
HelloAgainInterceptor.sayHelloAgain();
}
}
If this delegation is not an option for you, you can also use Advice to inline the code from a template class:
class HelloAgainAdvice {
#Advice.OnMethodExit
static void sayHelloAgain() {
System.out.println("Hello again");
}
}
Instead of the MethodDelegation, you would use this class via Advice.to(HelloAgainAdvice.class). As the code is copied, you will not be able to set break points but your redefined class will be self-contained.

Static methods are sort of code smell?

I am recently working on TDD with JUnit and Mockito. For some purpose within a method, I am using an Util class (an utility class having methods in project context). The thing is what I am facing is how to mock such classes in Mockito. I am not able to find as such implementation regarding static methods in Mockito. Some suggest using PowerMock on top of Mockito but wouldn't that replace my JunitMockitoRunner?
The way I am using the static function is:
public void doSomething(int x){
//Some code
Y y = Util.someStaticMethod(x);
//Some more code
}
EDIT : Also I read somewhere that using static methods is a code smell and is a sign of bad design. So how should I be refactoring the design and what advantages will I be having as a result?
How should I be refactoring the design and what advantages will I be having as a result?
Well, if you need to mock the static utility method, then make it an instance method of an injectable object, so that you can inject a mock implementation of this object. The advantage is that it makes your code more testable:
public class Util {
public Y someInstanceMethod(X x) {
...
}
}
public class ClassToBeTested {
private Util util;
public ClassToBeTested(Util util) {
this.util = util;
}
public void doSomething(int x){
//Some code
Y y = util.someInstanceMethod(x);
//Some more code
}
}
public class ClassToBeTestedTest {
public void testDoSomething() {
Util mockUtil = mock(Util.class);
ClassToBeTested t = new ClassToBeTested(mockUtil);
when(mockUtil.someInstanceMethd(3)).thenReturn(...);
...
}
}
That's the main selling point of dependency injection: it makes your code testable.
I do something like that for mocking static Util classes with jMockit.
public class UtilsTest {
#After
public void teardown() {
Mockit.restoreAllOriginalDefinitions();
}
#Test
public void testMyUtil() {
Mockit.setUpMocks( MockUtil.class );
}
}
#MockClass(realClass=Util.class)
public class MockUtil{
#Mock
public static MySpecialClass someStaticMethod(int x) {
return Mockito.mock(MySpecialClass.class);
}
}

Getting data out of JUnit test class in threaded environment

I am running some JUnit tests programatically with JUnitCore, and I want to get some data out of the test class once it is finished (so #AfterClass). Here is a pseudocode example of the constraints I am working under:
public class A {
public static String testData;
public static void runTest() {
JUnitCore juc = new JUnitCore();
juc.run(B);
// This is where I would like to access testData for this
// particular run
}
public static void setTestData(String s) {
testData = s;
}
}
public class B {
// Some #Test methods and stuff omitted
#AfterClass
public static void done(String s) {
A.setTestData(someData);
}
}
My problem is that different threads might be calling runTest(), so testData might be wrong. How do I work around this? I'm so lost.
If you really need/want to go with this design, you can make testData a java.lang.ThreadLocal<String>. This will solve the multi-threading issue.

Changing method execution in runtime (Java)

I am a Software Engineer in Test, and I am trying to write code that can replace production side method so that test can execute those instead. Basically, I do not want to modify production code for testability.
Here is a simple scenario:
public class Foo {
public static void foo() {
printA();
}
public static void printA() {
System.out.println("A");
}
public static void printB() {
System.out.println("B");
}
}
public class Foobar {
public Foobar() {
}
public void test() {
Foo.foo();
}
public static void main(String[] args) {
//Try changing the method here
new Foobar().test();
}
}
As you can see, when the main executes, it will print "A" since it calls the method printA on static method foo(). Now on runtime, is there a way I can inject or modify such that foo will call printB instead of printA?
Thank you for all the help!
Look at AspectJ.
It provides advices, which can be used to execute some code around a method (before and after its execution), including bypassing the call to original method altogether and returning some arbirary value
If you're just doing this for testing out classes, you could use a mocking framework to mock the classes on the server. I like Mockito.
You can do it yourself using the java reflection api, or you can you use a tool like PowerMock.

Categories

Resources