Why mockito make a call for stubbed method.
Why it make an actual call for func under when..thenReturn
I have checked when doing debugging.
#Test
public void function(){
MyClassChild obj = mock(MyClassChild.class);
when(obj.func("abc")).thenReturn(3);
}
...
class MyClass {
public int func(String s) {
if (s.equals("abc"))
return 3;
else
return 1;
}
}
class MyClassChild extends MyCLass {
}
I attempted to replay your issue by having the following test:
public class StackTest {
#Test
public void mockedFunction() {
MyClass obj = mock(MyClass.class);
when(obj.func("abc")).thenReturn(3);
assertEquals(3, obj.func("abc"));
}
#Test
public void function() {
MyClass obj = new MyClass();
assertEquals(7, obj.func("abc"));
}
}
and
public class MyClass {
public int func(String s) {
if (s.equals("abc"))
return 7;
else
return 9;
}
}
All tests where executed successfully. Can you show how you are invoking the test?
Related
tl;dr;
I am looking for a way to set a "condition" attribute on a Spring Cacheable annotation from another class. Is there such a way?
Using Spring Cache where it should cache ONLY whenever a certain method has been invoked. This method is in ClassA, the method (data) to cache is in ClassB. What I want to do is something like this:
public ClassA implements myInterface {
...
private Boolean inProcess = false;
public void cacheWhenThisMethodCalled() {
try {
inProcess = true;
// do work here, somewhere along the line
// the method in ClassB gets called
} finally {
inProcess = false;
}
}
ClassB:
public ClassB {
...
#Cacheable(cacheNames={"aCache"}, condition="#classA.inProcess")
public ValueClass findValueClass(UUID id)
However, I can't find the right condition for the SPeL to work. I have tried many combinations, none successfully. ClassA is a SpringBean, but the #Bean annotation returns the Interface, not the class. Can this be made to work? Or is there a better way?
Use a ThreadLocal - you would need to do that anyway for thread safety - otherwise a different thread can change the field.
This works fine...
#SpringBootApplication
#EnableCaching
public class So47580936Application {
public static void main(String[] args) {
SpringApplication.run(So47580936Application.class, args);
}
#Bean
public ApplicationRunner runner(Bar bar) {
return args -> {
bar.cacheFromHere();
bar.dontCacheFromHere();
};
}
#Component
public static class Foo {
#Cacheable(cacheNames = "foos", condition = "T(com.example.So47580936Application$Bar).cacheit()")
public String foo() {
System.out.println("here");
return "foo";
}
}
#Component
public static class Bar {
private static final ThreadLocal<Boolean> cacheit = new ThreadLocal<>();
#Autowired
private Foo foo;
public static boolean cacheit() {
return cacheit.get() == null ? false : cacheit.get();
}
public void cacheFromHere() {
try {
this.cacheit.set(true);
System.out.println("Cache:" + this.foo.foo());
System.out.println("Cache:" + this.foo.foo());
}
finally {
this.cacheit.remove();
}
}
public void dontCacheFromHere() {
System.out.println("Don't:" + this.foo.foo());
System.out.println("Don't:" + this.foo.foo());
}
}
}
result:
here
Cache:foo
Cache:foo
here
Don't:foo
here
Don't:foo
EDIT
Or, you can just make the ThreadLocal a #Bean ...
#SpringBootApplication
#EnableCaching
public class So47580936Application {
public static void main(String[] args) {
SpringApplication.run(So47580936Application.class, args);
}
#Bean
public ApplicationRunner runner(Bar bar) {
return args -> {
bar.cacheFromHere();
bar.dontCacheFromHere();
};
}
#Bean
public ThreadLocal<Boolean> cacheit() {
return new ThreadLocal<>();
}
#Component
public static class Foo {
#Cacheable(cacheNames = "foos", condition = "#cacheit.get() ?: false")
public String foo() {
System.out.println("here");
return "foo";
}
}
#Component
public static class Bar {
#Autowired
private ThreadLocal<Boolean> cacheit;
#Autowired
private Foo foo;
public void cacheFromHere() {
try {
this.cacheit.set(true);
System.out.println("Cache:" + this.foo.foo());
System.out.println("Cache:" + this.foo.foo());
}
finally {
this.cacheit.remove();
}
}
public void dontCacheFromHere() {
System.out.println("Don't:" + this.foo.foo());
System.out.println("Don't:" + this.foo.foo());
}
}
}
I have a static method which will be invoking from test method in a class as bellow
public class MyClass
{
private static boolean mockMethod( String input )
{
boolean value;
//do something to value
return value;
}
public static boolean methodToTest()
{
boolean getVal = mockMethod( "input" );
//do something to getVal
return getVal;
}
}
I want to write a test case for method methodToTest by mocking mockMethod.
Tried as bellow and it doesn't give any output
#Before
public void init()
{
Mockit.setUpMock( MyClass.class, MyClassMocked.class );
}
public static class MyClassMocked extends MockUp<MyClass>
{
#Mock
private static boolean mockMethod( String input )
{
return true;
}
}
#Test
public void testMethodToTest()
{
assertTrue( ( MyClass.methodToTest() );
}
To mock your static method:
new MockUp<MyClass>()
{
#Mock
boolean mockMethod( String input ) // no access modifier required
{
return true;
}
};
To mock the static private method:
#Mocked({"mockMethod"})
MyClass myClass;
String result;
#Before
public void init()
{
new Expectations(myClass)
{
{
invoke(MyClass.class, "mockMethod", anyString);
returns(result);
}
}
}
#Test
public void testMethodToTest()
{
result = "true"; // Replace result with what you want to test...
assertTrue( ( MyClass.methodToTest() );
}
From JavaDoc:
Object mockit.Invocations.invoke(Class methodOwner, String methodName, Object... methodArgs)
Specifies an expected invocation to a given static method, with a given list of arguments.
There is another way of mocking static methods using JMockit (using Delegate class). I find it more convenient and elegant.
public class Service {
public String addSuffix(String str) { // method to be tested
return Utils.staticMethod(str);
}
}
public class Utils {
public static String staticMethod(String s) { // method to be mocked
String suffix = DatabaseManager.findSuffix("default_suffix");
return s.concat(suffix);
}
}
public class Test {
#Tested
Service service;
#Mocked
Utils utils; // #Mocked will make sure all methods will be mocked (including static methods)
#Test
public void test() {
new Expectations {{
Utils.staticMethod(anyString); times = 1; result = new Delegate() {
public static String staticMethod(String s) { // should have the same signature (method name and parameters) as Utils#staticMethod
return ""; // provide custom implementation for your Utils#staticMethod
}
}
}}
service.addSuffix("test_value");
new Verifications {{
String s;
Utils.staticMethod(s = withCapture()); times = 1;
assertEquals("test_value", s); // assert that Service#addSuffix propagated "test_value" to Utils#staticMethod
}}
}
}
Reference:
https://jmockit.github.io/tutorial/Mocking.html#delegates
https://jmockit.github.io/tutorial/Mocking.html#withCapture
I have a static method which will be invoking from test method in a class as bellow
public class MyClass
{
private static boolean mockMethod( String input )
{
boolean value;
//do something to value
return value;
}
public static boolean methodToTest()
{
boolean getVal = mockMethod( "input" );
//do something to getVal
return getVal;
}
}
I want to write a test case for method methodToTest by mocking mockMethod.
Tried as bellow and it doesn't give any output
#Before
public void init()
{
Mockit.setUpMock( MyClass.class, MyClassMocked.class );
}
public static class MyClassMocked extends MockUp<MyClass>
{
#Mock
private static boolean mockMethod( String input )
{
return true;
}
}
#Test
public void testMethodToTest()
{
assertTrue( ( MyClass.methodToTest() );
}
To mock your static method:
new MockUp<MyClass>()
{
#Mock
boolean mockMethod( String input ) // no access modifier required
{
return true;
}
};
To mock the static private method:
#Mocked({"mockMethod"})
MyClass myClass;
String result;
#Before
public void init()
{
new Expectations(myClass)
{
{
invoke(MyClass.class, "mockMethod", anyString);
returns(result);
}
}
}
#Test
public void testMethodToTest()
{
result = "true"; // Replace result with what you want to test...
assertTrue( ( MyClass.methodToTest() );
}
From JavaDoc:
Object mockit.Invocations.invoke(Class methodOwner, String methodName, Object... methodArgs)
Specifies an expected invocation to a given static method, with a given list of arguments.
There is another way of mocking static methods using JMockit (using Delegate class). I find it more convenient and elegant.
public class Service {
public String addSuffix(String str) { // method to be tested
return Utils.staticMethod(str);
}
}
public class Utils {
public static String staticMethod(String s) { // method to be mocked
String suffix = DatabaseManager.findSuffix("default_suffix");
return s.concat(suffix);
}
}
public class Test {
#Tested
Service service;
#Mocked
Utils utils; // #Mocked will make sure all methods will be mocked (including static methods)
#Test
public void test() {
new Expectations {{
Utils.staticMethod(anyString); times = 1; result = new Delegate() {
public static String staticMethod(String s) { // should have the same signature (method name and parameters) as Utils#staticMethod
return ""; // provide custom implementation for your Utils#staticMethod
}
}
}}
service.addSuffix("test_value");
new Verifications {{
String s;
Utils.staticMethod(s = withCapture()); times = 1;
assertEquals("test_value", s); // assert that Service#addSuffix propagated "test_value" to Utils#staticMethod
}}
}
}
Reference:
https://jmockit.github.io/tutorial/Mocking.html#delegates
https://jmockit.github.io/tutorial/Mocking.html#withCapture
I am trying to write really simple test with Mockito. I wrote small piece of code:
public class FlowTests {
#Mock
Calculator mockCalc = Mockito.mock(Calculator.class);
ConsoleView mockView = Mockito.mock(ConsoleView.class);
#Test
public void a01_Test() {
final String s = "2+2*2";
Controller c = new Controller();
c.setCalc(mockCalc);
Mockito.when(mockView.getFormule()).thenReturn(s); // I am not sure if it works
c.setView(mockView);
c.handle();
// TODO check if evaluate method has been invoked with "2+2*2"
}
}
Here you can see classes associated with this test:
public class Controller {
private IView view = new ConsoleView();
private ICalculator calc = new Calculator();
Double value = null;
public void handle() {
String formule = view.getFormule();
Double value = calc.evaluate(formule);
if (value != null) {
System.out.println("Result: ");
view.appendAnswer(value);
}
}
public void setCalc(ICalculator calc) {
this.calc = calc;
}
public void setView(IView view) {
this.view = view;
}
}
public class Calculator implements ICalculator {
public double evaluate(String s) {
...
char[] formuleChar = s.toCharArray();
result = calc.eval(formuleChar);
return result;
}
}
public class ConsoleView implements IView {
public String getFormule() {
... // getting s from console
return s;
}
public void appendAnswer(double r) {
System.out.println(r);
}
}
First goal of my test is to mock function getFormule() in ConsoleView to return always String s = "2+2*2". I did it but I am not sure if it works.
The main goal is to check if method evaluate() in Calculator class has been invoked with the same String. I have no idea how to that.
I cannot modify my code. I can only write a test.
Thank you in advance for your help!
Try something like this:
// check if evaluate method has been invoked with "2+2*2"
verify(mockCalc).evaluate("2+2*2");
I want to override a previously defined expectation in JMockit. This is what I tried (see code below) -- I have a private class where I record all the common expectations and I replay it in various test methods. However, one of my method needs most of the common expectations except for few. First, I am calling the CommonNonStrictExpectations private class and then defining test specific expectations in my testMethod1 with a hope that what I defined here overrides what I have defined earlier. I dont think this way of overriding works, is there a way that works?
//MyClassTest.java
import MyClass;
public class MyClassTest {
#Mocked Someobject object;
#Test
public void testMethod1() throws Exception {
new CommonNonStrictExpectations() {};
new NonStrictExpectations() {
{
object.getInt(anyInt); returns (-1);
object.getString(anyInt); returns ("failure");
}
};
System.out.println("position: " + object.getInt(1));
System.out.println("exec status: " + object.getString(1));
MyClass m = new MyClass();
m.method(object, -1);
}
private class CommonNonStrictExpectations extends NonStrictExpectations {
public CommonNonStrictExpectations () throws Exception {
object.getInt(anyInt); returns (anyInt);
object.getString(anyInt); returns ("success");
}
}
}
//MyClass.java
import Someobject;
public class MyClass {
public void method (Someobject someobject, int i) {
String status = someobject.getString(i);
if (status.equalsIgnoreCase("success")) {
print(someobject, "success");
} else if (status.equalsIgnoreCase("failure")) {
print(someobject, "failure");
} else
print(someobject, "");
}
private String print(Someobject someobject, String status) {
return someobject.printMessage (status);
}
}
// Someobject.java
public class Someobject {
public String getString(int i) {
if (i < 0)
return "failure";
else if (i > 0)
return "success";
else
return "";
}
public int getInt(int k) {
return k;
}
public String printMessage (String status) {
return "status is: " + status;
}
}