Verify that a private method was NOT executed JMockit - java

I have looked around for this question a bit and have not found exactly what I need. I have learned a bit more about JMockit and mocking. Which is good. Seems like everyone wants to know how to make sure something has executed. I would like to learn the opposite.
Ok - I am writing a test to check a not so happy path in a public method. The method that is being tested is void so I can't really assert the results. What I would like to do is verify that a method was NOT executed in this test case.
For example:
class ClassToTest {
private void method(String arg){}
public void publicMethod(String arg0, String arg1){
if(false){
//this method should never get called.
method(arg0);
}
}
}
class TestingClass{
#Tested
private ClassToTest classToTest = new ClassToTest();
#Test
public void testCheckingIfPrivateMethodWasCalled(){
classToTest.publicMethod("string1", "string2");
new Verifications() {
{
//At this point I am trying something like
Deencapsulation.invoke(classToTest, "method", "string1");
times = 0; //Also tried maxTimes = 0;
//Through debug it looks like the invoke is doing what it's named...
//invoking the private method, I don't want to invoke.
//How do I check that ClassToTest#method was not called?
}
}
}
}
What I am getting as results for the test case is a java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter. Which is on the line of times = 0;.
I know the invoke is executing the private method. I am left scratching my head trying to figure out how to "check" that said method is called with out invoking/executing it.
Thanks.

One way of doing it is with the MockUp API for faking:
import static org.junit.Assert.assertFalse;
import org.junit.Test;
import mockit.Mock;
import mockit.MockUp;
import mockit.Tested;
public class TestingClass {
#Tested
private ClassToTest classToTest = new ClassToTest();
#Test
public void testCheckingIfPrivateMethodWasCalled() {
PrivateMethodCheckMockUp mockUp = new PrivateMethodCheckMockUp() {
#Mock
private void method(String arg) {
calledPrivate = true;
}
};
classToTest.publicMethod("string1", "string2");
assertFalse(mockUp.calledPrivate);
}
class PrivateMethodCheckMockUp extends MockUp<ClassToTest> {
boolean calledPrivate = false;
#Mock
private void method(String arg) {
calledPrivate = true;
}
}
}

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. ;)

Skip null check in mockito

I am trying to write unit test cases for one of the methods in code.Below is the method
public boolean isValid() {
if(object == null)
return false
//do something here and return value.
}
The object is created by this method which is done before without getter setter method.
private Object returnObject() {
object = Axis2ConfigurationContextFactory.getConfigurationContext();
return object;
}
When I try to test isValid(), the object is always null, so it never goes in the code to do something.
I was checking if there is any way to skip that line or make the object not null. I also tried creating an object using returnObject method. But it uses Axis library classes which throws error if it does not find certain data. What can be done in this case? I am dealing with legacy code so any pointers would be helpful.
Edit : Adding test implementation.
#PowerMockIgnore({ "javax.xml.*", "org.w3c.dom.*", "javax.management.*" })
public class ClassTest {
private ClassTest classTestObj;
#BeforeMethod
public void callClassConstructor() {
classTestObj = //call class constructor
}
#BeforeClass
public void setUpClass() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public boolean isValidTest() {
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
As I mentioned in the before comment, you can make use of MockedStatic to mock the static method - https://javadoc.io/static/org.mockito/mockito-core/4.4.0/org/mockito/Mockito.html#static_mocks
So your code will somewhat look like the below one if you are making use of Mockito instead of PowerMockito.
#RunWith(MockitoJUnitRunner.class)
public class ClassTest
{
#Mock
private Object mockAxis2ConfigurationContextFactoryObject;
#Test
public boolean isValidTest() {
try (MockedStatic<Axis2ConfigurationContextFactory> mockedStatic = mockStatic(Axis2ConfigurationContextFactory.class)) {
mockedStatic.when(()->Axis2ConfigurationContextFactory.getConfigurationContext()).thenReturn(mockAxis2ConfigurationContextFactoryObject);
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}

How to test void method with private method calls using Mockito

I have the following piece of code
public class A extends B {
private boolean workDone = false;
#Override
public void publicMethod(boolean flag) {
if (!workDone) {
privateMethod();
workDone = true;
}
super.publicMethod(flag);
}
private void privateMethod() {
// some logic here
}
}
I'm new to mocking. I have following doubts. I'm trying to test the public method.
is it possible for me to assert the value of private variable workDone?
is it possible to verify the method call in the super class?
How can I mock the private method call in the method?
If you really want to verify it, you need to change your A class and extract the super call into a private method:
public class A extends B {
private boolean workDone = false;
#Override
public void publicMethod(final boolean flag) {
if (!workDone) {
privateMethod();
workDone = true;
}
callParentPublicMethod(flag);
}
private void callParentPublicMethod(final boolean flag) {
super.publicMethod(flag);
}
private void privateMethod() {
System.out.println("A: privateMethodCalled");
}
}
after this is done you can use PowerMock to verify private method invocations:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ A.class })
public class ATest {
#Test
public void publicMethod_test_false() throws Exception {
A spy = PowerMockito.spy(new A());
spy.publicMethod(false);
PowerMockito.verifyPrivate(spy).invoke("privateMethod");
PowerMockito.verifyPrivate(spy).invoke("callParentPublicMethod", false);
}
#Test
public void publicMethod_test_true() throws Exception {
A spy = PowerMockito.spy(new A());
spy.publicMethod(true);
PowerMockito.verifyPrivate(spy).invoke("privateMethod");
PowerMockito.verifyPrivate(spy).invoke("callParentPublicMethod", true);
}
}
Hope this helps.
When doing unittesting we verify the public observable behavior of the code under test. This is the return values delivered by the CUT and its communication with dependencies.
The private variable and the private methods inside the CUT are implementation details we don't want to test (explicitly) because we want them to be changeable without braking our test.
In rare cases the call to super class methods can be considered as "communication with dependency". In that case you create a spy() of the CUT. But usually this should be considered implementation detail too...
No. Private variables cannot be accessed other than via reflection. Which is usually not preferred, especially in unit tests.
Yes, assuming you get some assertable change do to super class method call. Like the change in the boolean flag
Yes you can using powermockito. For more see here.
Testing Private method using mockito

JMockit - Partial mocking and mocked parent

I would like to test (using JMockit) a class that looks like this:
class MyClass extends ComplexParentClass {
public void testedMethod() {
...
}
private int complexPrivateMethod() {
...
}
}
I can't change the class. The problem is that the ComplexParentClass has a complex constructor, which makes it hard to test. So I would like to mock the parent class. I would also like to mock the complex private method. But is something like that even possible?
I tried the following:
class MyClassTest {
#Tested
MyClass myClass;
// mock the parent
#Mocked
ComplexParentClass complexParentClass;
#Test
public void test() {
new Expectations(myClass) {{
// partially mock the private method
Deencapsulation.invoke(myClass, "complexPrivateMethod"); result = 0;
}};
myClass.testedMethod();
}
}
This leads to an "already mocked" exception though.
Does anybody have an idea how to approach this?
Have you tried using MockUps? Something like this would mock complexPrivateMethod only:
#Test public void test() {
new MockUp<ComplexParentClass> () {
#Mock private int complexPrivateMethod() { return 0; }
};
//do something with MyClass
}

JUnit - test that a method has been called

I'm new to unit testing, and I'm trying to test that a method has been called. The method in question doesn't return anything.
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
I want to be able to test that the processFoo method is being called, but I don't know how to do that.
If mocking is required, then I have to use JMockit. Thanks!
Sorry I'm a little late to the party, but I have a couple of ideas for you.
First, you mention that one option is to use JMockit--that's great as it gives you a lot of flexibility. If you use JMockit, then the visibility of your processFoo() method doesn't much matter. Let's see what that might look like:
public class Subject {
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
private void processFoo(boolean b) {
System.out.println("b = " + b);
}
private void processSomethingElse(boolean bb) {
System.out.println("bb = " + bb);
}
}
So, one caveat with this option, though is that I'm going to assume processFoo() is a method on your test subject and I'm going to use a partial mock to change the test subject--not something I really like to do, but this is an example. In general, it is best to only mock the dependencies of your test subject rather than behavior of the test subject itself--you have been advised! Note that the processFoo() method of the test subject is private. I'm going to substitute a method for the test with JMockit's partial mocking and the visibility of that new method does not have to match the original.
import static org.assertj.core.api.Assertions.assertThat;
import mockit.Mock;
import mockit.MockUp;
import mockit.integration.junit4.JMockit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(JMockit.class)
public class SubjectTest {
private Subject testSubject = new Subject();
private boolean processFooCalled = false;
#Before
public void setup() {
new MockUp<Subject>() {
#Mock
public void processFoo(boolean b) {
processFooCalled = true;
};
};
}
#Test
public void should_call_processFoo() {
testSubject.example(true);
assertThat(processFooCalled).isTrue();
}
#Test
public void should_not_call_processFoo() {
testSubject.example(false);
assertThat(processFooCalled).isFalse();
}
}
Ok, so that was the first option. It's actually a little easier if you forget JMockit for this one, assuming you are able to subclass your test subject and override the processFoo() method:
public class Subject {
public void example (boolean foo) {
if (foo) {
processFoo(foo);
}
else if (foo==false) {
processSomethingElse(foo);
}
}
protected void processFoo(boolean b) { // NOTE: protected access here!
System.out.println("b = " + b);
}
private void processSomethingElse(boolean bb) {
System.out.println("bb = " + bb);
}
}
So, in this case, the strategy is simply to subclass your test subject and replace the implementation of the method you wish to observe being called. It might look like this:
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
public class SubjectTest2 {
private Subject testSubject = new TestableSubject();
private boolean processFooCalled = false;
#Test
public void should_call_processFoo() {
testSubject.example(true);
assertThat(processFooCalled).isTrue();
}
#Test
public void should_not_call_processFoo() {
testSubject.example(false);
assertThat(processFooCalled).isFalse();
}
class TestableSubject extends Subject {
#Override
protected void processFoo(boolean b) {
processFooCalled = true;
}
}
}
Give it a whirl. Hope it helps!
You could use a counter variable in your class and increment it whenever the method is called, or use a print statement. If you don't have access to the processFoo method, a simple approach would be to do this at the time that processFoo is called in another method, if that's the only place where it can possibly be called.
For example:
public static int processFooCalls = 0;
// ...
public void example (boolean foo) {
if (foo) {
processFoo(foo);
processFooCalls += 1;
// and/or
System.out.println("processFoo method was called");
}
// ...
}
public static void main (String[] args) {
// main routine here...
System.out.println("'processFoo' was called " + processFooCalls + " times.");
}
If processFoo can be called elsewhere, and you need to consider this possibility as well, then you'll need to have access to the processFoo code in order to do this, e.g.:
void processFoo( boolean b ) {
// increment number of times processFoo was called here, and/or print, as follows
processFooCalls += 1;
System.out.println("called processFoo method!");
/* some functionality */
}
Looking at the JMockit documentation, you will need the following tools:
Static Mocking: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#staticPartial
Invocation Counts: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#constraints
Combining the two in a test (my syntax may be a little off since I'm more accustomed to Mockito, but the concept should hold):
#Test
public void someTestMethod(#Mocked({"processFoo"}) final ExampleClass exampleclass)
{
new Expectations() {{
exampleclass.processFoo(); times = 1;
}};
exampleclass.example(true);
}
This should mock the processFoo method, leaving everything else intact, and checks to make sure it is called exactly once.
Don't consider doing any kind of partial mocking for this, all you're doing in that case is ensuring that if you want to refactor your code your tests will fail. There is a mantra in unit testing - "never test private methods".
What you should be doing is testing that the method you call conforms to the behaviour you want to see. In this case what happens when foo is true is what's important, not that it calls processFoo. So if foo is true you want to be testing that the action processFoo carries out is true and nothing else.

Categories

Resources