I have a class WidgetProcessor that has a dependency on another class, FizzChecker:
public class FizzChecker {
public boolean hasMoreBuzz() {
// Sometimes returns true, sometimes returns false.
}
}
This hasMoreBuzz() method is invoked from inside WidgetProcessor like so:
public class WidgetProcessor {
public int process() {
while(fizzChecker.hasMoreBuzz()) {
// ... process stuff in here
}
}
}
I want to write test cases for when:
fizzChecker.hasMoreBuzz() returns false the 1st time it is called (hence the loop never executes)
fizzChecker.hasMoreBuzz() returns false on the 5th time it is called
I'm trying to figure out how to accomplish this with Mockito. So far my best (terrible) attempt:
WidgetProcessor fixture = new WidgetProcessor();
FizzChecker mockFizzChecker = Mockito.mock(FizzChecker.class);
// This works great for the first test case, but what about the 2nd
// where I need it to return: true, true, true, true, false?
Mockito.when(mockFizzChecker).hasMoreBuzz().thenReturn(false);
fixture.setFizzChecker(mockFizzCheck);
fixture.process();
// Assert omitted for brevity
Thanks in advance.
You can pass in multiple values to thenReturn, or keep chaining. Successive calls to the stubbed method will return the actions in sequence, repeating the final action for all calls. Examples:
// will return true four times, and then false for all calls afterwards
when(mockFizzChecker.hasMoreBuzz()).thenReturn(true, true, true, true, false);
when(mockFizzChecker.hasMoreBuzz())
.thenReturn(true)
.thenReturn(true)
.thenReturn(true)
.thenReturn(true)
.thenReturn(false);
// you can also switch actions like this:
when(someOtherMock.someMethodCall())
.thenReturn(1, 2)
.thenThrow(new RuntimeException());
You'll probably want to set them up separately:
public class WidgetProcessorTest {
private WidgetProcessor processor;
private FizzChecker mockFizzChecker;
#Before public void setUp() {
processor = new WidgetProcessor();
mockFizzChecker = Mockito.mock(FizzChecker.class);
processor.setFizzChecker(mockFizzChecker);
}
#Test public void neverHasBuzz() {
when(mockFizzChecker.hasMoreBuzz()).thenReturn(false);
processor.process();
// asserts
}
#Test public void hasFiveBuzzes() {
when(mockFizzChecker.hasMoreBuzz())
.thenReturn(true, true, true, true, false);
processor.process();
// asserts
}
}
Last note: In reality, you may find you need to coordinate multiple calls (such as hasMoreBuzz and getNextBuzz). If it starts to get complicated, and you foresee writing this in a lot of tests, consider skipping Mockito and instead just implementing a FakeFizzChecker.
Try using Answers. This will allow you to execute code when the hasMoreBuzz() method is called.
Look at the example in the link provided above. If you create an Answer object, and implement the answer() method to keep a counter, you can take action based on the value of that counter.
Edit: I wrote a quick test program to verify this. Here it is:
package com.ejk;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;
public class SO {
#Test
public void testIt() {
IFoo mock = mock(IFoo.class);
MyAnswer myAnswer = new MyAnswer();
when(mock.doFoo()).then(myAnswer);
for (int i=1; i<10; i++) {
System.out.println(i+ ") " + mock.doFoo());
}
}
class MyAnswer implements Answer<Boolean> {
int counter = 1;
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return (counter++ == 5) ? Boolean.FALSE : Boolean.TRUE;
}
}
interface IFoo {
boolean doFoo();
}
}
Related
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);
}
}
I am trying to do when().thenReturn() but facing issues. Following is the sample code that I came up with for SOers:
import java.util.List;
public class Sample {
public void function(List<SampleA> list) {
for (SampleA s : list) {
List<SampleB> nameList = s.v1;
for (SampleB m : nameList) {
SampleC value = m.getV2();
if (value != null) {
doSomething(value);
} else {
LOGGER.warn("No valid value");
}
}
}
}
}
public class SampleA{
List<SampleB> v1;
}
public class SampleB{
SampleC v2;
public SampleC getV2(){
return this.v2;
}
}
This might be silly but I just want to understand why can't I do:
SampleB sampleB = new SampleB();
when(sampleB.getV2()).thenReturn(any(SampleC.class));
I'm guessing that you are trying to test Sample.function and are trying to work out how to mock SampleC values. If so, then your code should probably look something like:
#Test
void testFunction() {
SampleC mockC = mock(SampleC.class);
SampleB mockB = mock(SampleB.class);
SampleA mockA = mock(SampleA.class);
when(mockB.getV2()).thenReturn(mockC);
when(mockA.getV1()).thenReturn(List.of(mockB));
Sample sample = new Sample();
sample.function(List.of(mockA));
// verify doSomething was called with mockC as its argument
when(mockB.getV2()).thenReturn(null);
sample.function(List.of(mockA));
// verify "No valid value" was logged
}
I've added a getV1 method rather than direct access to the field because my fingers refuse to write the code that directly accesses a public field :-)
If you're struggling with verifying that doSomething was called then that's where argument matching comes in. Ideally you'd have a SomethingDoer that you inject into your sample:
interface SomethingDoer {
void doSomething(SampleC sample);
}
class Sample {
private final SomethingDoer somethingDoer;
public Sample(SomethingDoer somethingDoer) {
this.somethingDoer = somethingDoer;
}
}
Then you'd add the following to your test:
SomethingDoer doer = mock(SomethingDoer.class);
Sample sample = new Sample(doer);
...
verify(doer).doSomething(mockC);
Also note that the code above is poor style: the tests should be split up with the setup code in a #BeforeEach method. I've just put it in a single test to keep the answer simple.
any(…) is an ArgumentMatcher. It is used to match arguments. You cannot use it to return instances of classes. What would "any SampleC" be?
You'd use it with mock objects, like so:
SampleInterface sample = Mockito.mock(SampleInterface.class);
when(sample.function(any(List.class))).thenReturn(new ArrayList<>());
// or: .thenAnswer(a -> new ArrayList<>()); to return a new instance for each call
you can't use ArgumentMatchers inside thenReturn or thenAnswer. You have to specify exactly what to return. For Example:
SampleB sampleB = mock(SampleB.class)
when(sampleB.getV2()).thenReturn(new SampleC());
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;
}
}
}
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.
I'd like to verify that calls against a mock only ever happen with some expected argument values, and never with anything else.
public interface ADependancy {
public void method(String parameter, String otherParameter);
}
public class Foo {
private ADependancy myHelper;
public Foo(ADependancy helper) {
this.myHelper = helper;
}
public void good() {
myHelper.method("expected","expected");
myHelper.method("expected","expected");
myHelper.method("expected","expected");
}
public void bad() {
myHelper.method("expected","expected");
myHelper.method("expected","UNexpected");
myHelper.method("expected","expected");
}
}
I tried this:
public class FooTest extends TestCase {
private ADependancy mock =mock(ADependancy.class);;
private Foo foo = new Foo(mock);
#Test
public void testGood() {
foo.good();
validateOnlyCalledWithExpected();
}
#Test
public void testBad() {
foo.bad();
validateOnlyCalledWithExpected();
}
private void validateOnlyCalledWithExpected() {
verify(mock,atLeastOnce()).method(eq("expected"),eq("expected"));
verify(mock,never()).method(not(eq("expected")),not(eq("expected")));
}
}
Expecting testBad to fail, but instead the test passes. If method only takes one parameter, this works as expected.
It was a logic mistake.
I wanted to assert that each argument is never anything but the expected value.
But instead, what I was actually asserting was that it never happens that they are ALL not the expected value.
So with the way I had it, it did not fail as desired, because in fact, some of the arguments are not not the expected value, therefore the method is never called with all the parameters not the expected value, and the verify passes.
Thus, this works for what I wanted:
private void validateOnlyCalledWithExpected() {
verify(mock,atLeastOnce()).method(eq("expected"),eq("expected"));
verify(mock,never()).method(not(eq("expected")),anyString());
verify(mock,never()).method(anyString(),not(eq("expected")));
}
You could use the verifyNoMoreInteractions static method, documented at http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#finding_redundant_invocations.
verify(mock).method(eq("expected"),eq("expected"));
verifyNoMoreInteractions(mock);
Alternatively, you could write
verify(mock).method(eq("expected"),eq("expected"));
verify(mock,never()).method(anyString(),anyString());
because the second call to verify will disregard the calls that have already been verified.