I have a static method (foo) that calls another static method (bar). I would like to mock the response of bar in my test. Is this possible with PowerMockito or another tool? the only results I can find are for mocking statics inside of non-static methods.
public class SomeClass {
static List<String> foo() {
...
int barResult = bar();
...
}
static int bar() {
// make a database call
return DAO.getDao().runQuery();
}
}
And my test will call it like:
#RunWith(PowerMockRunner.class)
public class SomeClassTest {
#PrepareForTest(SomeClass.class)
#Test
public void fooTest() {
List<String> actualResult = SomeClass.foo();
assertTrue(...);
}
}
Am I going to have to mock the internals of bar? So mock the DAO?
You can't do that.
Only PowerMock allows you to mock static methods. But that works by "erasing" all static things within that class that gets "prepared" for testing by PowerMock.
If you were talking about ordinary methods, you could be going for Mockito spies, as those allow for partial mockings.
And just for the record: simply avoid using static, as using it leads to "hard to test" code.
In other words: instead of using the big ugly powermock hammer to "fix" your design problems... Consider fixing your broken design instead and thereby avoiding the need for PowerMock altogether!
And for the record: yes, you could solve your problem by mocking that static call on the DAO class (then you can control what bar() does indirectly. But again: that would just mean to put the "I tested it" label on code that should be reworked instead.
You can do:
#RunWith(PowerMockRunner.class)
#PrepareForTest({SomeClass.class, DAO.class})
public class SomeClassTest {
#Test
public void fooTest() {
PowerMockito.mockStatic(DAO.class);
Mockito.when(DAO.getDao().runQuery()).return(..);
List<String> actualResult = SomeClass.foo();
assertTrue(...);
}
}
Related
I'm trying to test a method that calls an external util static method for a check, and need to somehow mock it to return true / false conditions, here is a sample:
class foo {
public void methodToTest(){
..logic
boolean myCondition = SomeUtil.checkCondition(args);
..more logic
}
}
Is this possible to do with mockito only? If not directly, is there a way to replace the SameUtil method with reflection or something similar?
I saw people suggesting powermock, but they don't have mockito 3.x listed on their compatibility chart, is there a better option?
This seems like a pretty common case, not everything should be autowired or injected.
Option 1: factor out the static method call into a separate method and use Mockito spy:
class Foo {
public void methodToTest(){
checkCondition(args);
// ....
}
boolean checkCondition(Object args) {
return SomeUtil.checkCondition(args);
}
}
class FooTest {
#Spy
#InjectMocks
private Foo foo;
#Test
void methodToTest() {
//...
when(foo.checkCondition(yourArg)).thenReturn(true);
}
}
See the Spy documentation for more details:
Option 2: factor out verification into a class:
class ArgumentVerifier {
boolean checkArgument(Object args) {
return SomeUtil.checkCondition(args);
}
}
class Foo {
private ArgumentVerifier verifier;
public void methodToTest() {
verifier.checkArgument(args); // mock the verifier as you normally would
// ....
}
}
It is possible since Mockito 3.4.0: Mocking Static Methods With Mockito
But please be aware that:
injecting remains a more explicit way of expressing dependency on another object/service, especially external api
static helper methods rarely need to be mocked (especially if they depend only on their arguments)
This limits the number of cases where mocking a static method is the tool of choice, but it is worth having it under your belt.
I have a Util.java class which contains some functions as follows:
public Util {
UtilB b;
funcA() {
//someAction
String a = b.someMethod();
funcB();
}
funcB() {
//recursive call to funcB
funcC();
}
funcC() {
//some processing
}
}
While writing test case in Mockito, I did something as follows:
public UtilTest {
#Mocks
UtilB b;
#InjectMocks
Util test;
#Test
public funcA() {
when(b.someMethod()).thenReturn("");
test.funcA();
}
}
As can be seen above, I cannot mock a call to funcB() when funcA() is called. The call will go inside funcB(). I can shift funcB() in another class like someMethod() in UtilB and mock that class like UtilB b and the test will work without actually calling funcB(), but is that a good practice to go on about creating new classes?
Additionally, since I am testing class Util, it should not be good to make it a spy and then operate on it to mock a call to funcB() right?
Should I even Mock funcB() in the first place since test.funcA() will cover funcB() and funcC() as well?
Could someone please guide me what is a good practice in this scenario?
I have code similar to this
class Util{
public String transform(String str);
//lots of logic including ajax calls
return("Modified"+str);
}
public caseChange(String str){
//lots of logic including ajax calls
return str.toUpperCase()
}
class TextParser extends Util{
public String parse(str)
//lots of logic to modify str
str = caseChange(str);
//some more logic to modify str
return transform(str);
}
Is there anyway to mock the caseChange and transform methods to return some mocked data and prevent a call to the superclass when i call
String result = new TextParser().parse("hello")
in the unit test class to assert result.
The transform and changeCase are over simplified in my example. In reality they perform ajax calls and there is a ton of other logic. I want to mock them out so that can unit test just this part an then unit test the super methods later
You may need to create another subclass like
class TextParserForTest extends TextParser {
#Override
public String parse(String str) {
super.parse(str);
}
#Override
public String caseChange(String str) {
return "whatever";
}
}
edit : use mockito to this :
import static org.mockito.Mockito.*;
import org.junit.Test;
#Test
public void test() {
TextParser tp = mock(TextParser.class);
// all the methods that you want to test
when(tp.parse(any())).thenCallRealMethod();
when...
// all the methods that you want to mock
when(tp.caseChange(any()).thenReturn("whatever");
when...
}
In your given example: you simply don't do that. Your methods are only working on your inputs; so it should absolutely not matter where those methods are implemented.
In other words: it seems most appropriate for you to focus on contract checking tests only. Like:
#Test
public testWhatever() {
assertThat(new TextParser.parse("hello"), is("expected output"));
}
Yes, you can probably mock such things using Mockito/Powermock; but you shouldn't! You see, your production code is directly calling those methods; so you want to test that calling parse gives you expected results (while using all the code that will also run in a production setup!)
Edit: given your comment about that methods being "complicated". Then I suggest: do not use inheritance here. You should not make class B a subclass of A just to have easy access to some methods. In other words: inheritance is about modeling an IS-A relation. So, a TextParser is a Util? Doesn't sound very convincing.
Thus: you better turn to composition here. Your TextParser should use a Util object. And that one can be provided via dependency injection; and your need to mock with inherited methods vanishes completely!
You can use the spy functionality of Mockito. The spy calls real methods unless they are stubbed.
#Test
public void testParse() {
TextParser textParser = Mockito.spy(new TextParser());
when(textParser.caseChange(Matchers.anyString())).thenReturn("mocked");
Assert.assertEquals("Modifiedmocked", textParser.parse("hello"));
}
I have written a test to verify that a public method in my class is called. My test is failing as follows. Can anyone tell me why this happening?
Wanted but not invoked: `mockMyClass.runThis();
Actually, there were zero interactions with this mock.
class MyClass{
public void myMethod(){
runThis("hello");
}
}
public void runThis(String str){
return;
}
Test class
#Mock
MyClass mockMyClass;
MyClass myClass = new MyClass();
#Test
public void test(){
myClass.myMethod();
verify(mockMyClass).runThis(anyString());
}
You're not invoking against your mock, but rather the real class. You need to generate a mock, and then invoke on that mock. Try something like:
MyClass mock = mock(MyClass.class); // I'm using the methods rather than annotation here
mock.myMethod();
and assert on that. I'm not quite sure in the above where runThis() is, though. If it's on a contained class, then that's the thing to need to mock. If it's on the same class, then you can't use a mock per se, since the mock substitutes all functionality, and perhaps the Mockito spy() mechanism would be of use here. Section 13 of the doc advises more on this.
I want to make a JUnit test to assure that some classes don't use a specific set of methods (from another classes). Example
class MyClass
{
void myMethod()
{
otherClass.otherClassStaticMethod();
}
}
class myTest
{
void test()
{
assertFalse(CalledMethods.getMethodsCalledBy("myClass.myMethod").Contains("otherClass.otherClassStaticMethod"));
}
}
In this test I want to assure that myMethod doesn't invocate otherClassStaticMethod. How can I find what methods are being called inside a method in compile time (ignore methods called using reflection)? I thought about a .java parser, do you recommend any?
you can mock "otherClass" and verify that the method isn't invoked. E.g. using Mockito you can even specify in which order what methods are supposed to be invoked (under the condition their instances are mocks) and specify which methods are not allowed to be invoked
as coding.mof said, to mock static methods you should use PowerMock/PowerMockito:
example:
PowerMockito.mockStatic(OtherClass.class);
PowerMockito.verifyStatic(never());
OtherClass.otherClassStaticMethod();
It sounds like you should be using a mock library and let that handle it all for you. I'd recommend JMock as my library of choice. If you're using instance methods then this would be perfect for you - if, as your example shows, it's static methods then PowerMock may work*1.
With JMock, you'd have something like:
public class MyClass {
public MyClass(Dependency dependency) {
this.dependency = dependency;
}
void myMethod() {
dependency.someMethod();
}
}
#RunWith(JMock.class)
public class MyTest {
private Mockery context = new Mockery();
#Test
public void doesNotCallSomeMethod() {
Dependency dependency = context.mock(Dependency.class);
MyClass obj = new MyClass(dependency);
obj.myMethod(); <--- this will fail fast
}
}
When you call obj.myMethod, JMock will instantly report that you never said dependency should have any methods called. It will also tell you what method you DID call and what parameters you passed in if any
*1 I don't use PowerMock as I steer away from static methods unless they are pure functions