How to verify a method was called inside another method with Mockito - java

I'm fairly new to Mockito, and I've been looking for a way to verify that if I call the filter() method with the right string, that the foo method will get called once.
public class A
{
private final Config _config;
public A(Config config) { _config = config; }
public void filter(String str)
{
if(str.startsWith("a"))
{
if(str.contains("z"))
{
foo(config.getName());
}
}
}
private void foo(String bar)
{
(...)
}
}
Here is my current code:
#Test
public void testOne()
{
Config config = new Config(configFile);
A a = Mockito.spy(new A(config));
a.filter("abcz");
verify(a, times(1)).foo(someString);
}

Try to be more generic while such a test. If you don't need to specify what exactly argument should by passed then just use any():
import static org.mockito.ArgumentMatchers.any;
verify(a).foo(any(String.class));

Related

How to inject mocks into a class that has 1 constructor with parameters?

I have the following class (Condensed it to focus on issue instead of showing entire class):
#Component
public class ABCDEF {
private final Helper helper;
private final URI uri;
public ABCDEF(Helper helper, #Value("${endpoint.url}") URI uri) {
this.helper = helper;
this.uri = uri;
}
public void b(){
helper.toString();
}
}
For its test, I am looking to inject the mocks as follows but it is not working.
The helper comes up as null and I end up having to add a default constructor to be able to throw the URI exception.
Please advice a way around this to be able to properly inject the mocks. Thanks.
#RunWith(JUnitMockitoRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
#InjectMocks
private ABCDEF abcdef = new ABCDEF(
helper,
new URI("test")
);
// adding just to be able to throw Exception
public ABCDEFTest() throws URISyntaxException {
}
#Test
public void b() {
abcdef.b();
}
}
Note: Using Mockito version 1.10.19. Will need to stick to this version.
This should work:
#RunWith(MockitoJUnitRunner.class)
public class ABCDEFTest {
#Mock
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}
Or, instead of using #RunWith, you can initialize mock inside setUp method:
public class ABCDEFTest {
private Helper helper;
private ABCDEF abcdef;
#Before
public void setUp() throws URISyntaxException {
helper = Mockito.mock(Helper.class);
abcdef = new ABCDEF(
helper,
new URI("test")
);
}
#Test
public void b() {
abcdef.b();
}
}

Spy an already initialized Java object Mockito

I am using the Mocktio library to write some test cases, since I have an elaborate inhertance structure, I have a few objects which are instantiated in the parent class, and I would like to mock one of its function call. Does Mockito library provide any way to spy on a already initialized object?
Also, the object is not directly instantiable.
Similar to the following -
public class A {
protected static MyObject a;
public static void someMethod() {
a = myObjectBuilder.createObj();
}
}
And another class B looks something similar to
class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
// now mock behavior of some method of MyObject a
// Missing line to spy object a.
Mockito.doReturn(false).when(a).xyz();
/* Now call some method that triggers a.xyz()
again, it is not a direct call,
there are multiple layer of abstraction
*/
}
}
Edit: I have tried the following and it does not work
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
Basically, don't do initialisation in BeforeClass, it runs only once but
you need to have new spy in each test, or you must "reinitialise" spy object
before each test.
Please examine this code:
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.assertj.core.api.Assertions.assertThat;
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected static MyObject a;
public void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#Before
public void setUpBeforeTest() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(mock_object.xyz()).isTrue();
}
}
If you want it your way, please change:
public void someMethod() {
a = myObjectBuilder.createObj();
}
into:
public static void someMethod() {
a = myObjectBuilder.createObj();
}
You can't call non static method from static initialiser #BeforeClass:
class A {
protected static MyObject a;
public static void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
// Here we replace original object with our spy
A.a = mock_object;
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(a.xyz()).isFalse();
}
}
Another example (in this case we replace object a with mock (spy is not needed):
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected MyObject a;
public A() {
a = new MyObject("ggggg");
}
public String doSomethingWithA(){
if(a.xyz()){
return a.cos;
}
else{
return "aaaa";
}
}
}
#RunWith(MockitoJUnitRunner.class)
public class B {
#Mock
MyObject mock_object;
#InjectMocks
A systemUnderTest = new A();
#Test
public void mockTest1() {
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isEqualTo("aaaa");
}
#Test
public void mockTest2() {
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isNull();
}
}

mockito verifying polymorphic methods

I'm trying to verify call to a polymorphic method using mockito, and am confused about what the best way forward is.
Example Class
public class Library {
public boolean foo() {
return true;
}
public boolean foo(String s) {
return true;
}
public boolean foo(Integer s) {
return true;
}
}
The test class using mockito(ignore the fact that in LibraryTest class, Library is not the class-under-test, but rather I'm mocking it)
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class LibraryTest {
#Test public void testFoo1() {
Library mockLibrary = mock(Library.class);
mockLibrary.foo("Hi");
verify(mockLibrary).foo(any());
}
#Test public void testFoo2() {
Library mockLibrary = mock(Library.class);
verify(mockLibrary, never()).foo(any());
}
}
So both the verify statements don't compile, with the error "The method foo(String) is ambiguous for the type Library".
The error kind of makes sense, any() tries to return a captor based on the type of the argument but the argument could be Integer or String or void.
What I want to achieve is that in both the tests, a call to any of the foo methods is counted by the verify. In other words the first verify call should succeed if I called any of the foo methods and the second verify should fail if I call any of the foo methods.
Is there a way to make this happen?
You can use isA matcher
verify(mockLibrary).foo(isA(Integer.class));
verify(mockLibrary).foo(isA(String.class));
and btw use Mockito.spy instead of Mockito.mock when you only want to see if some methods have been called on the class under test
EDIT with example (written in few minutes, don't mind the code:)) based on the new op details.
public static class Library {
public boolean foo() {
return true;
}
public boolean foo(String s) {
return true;
}
public boolean foo(Integer s) {
return true;
}
public String x(){
return "";
}
public void y(){
return;
}
}
public static class ResponseProvider {
public boolean result;
}
#Test
public void testFoo1() {
final ResponseProvider provider = new ResponseProvider();
provider.result = false;
Library lib = Mockito.mock(Library.class, new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
if ((invocation.getMethod().getName().equals("foo"))) {
provider.result = true;
return true;
}
return invocation.callRealMethod();
}
});
//lib.foo();
//lib.x();
//lib.y();
assertTrue(provider.result);
}
First of all, You are mocking the same class which you are testing. Thats not advisable but still
Its giving this exception because mockito doesn't know which method you are verifying among the foo methods. If you want to make sure the method you invoked is called with the right value, you can either use isA(ClassName) matcher or use can use ArgumentCaptor.
Example of ArgumentCaptor
#Test public void testFoo1() {
Library mockLibrary = mock(Library.class);
mockLibrary.foo("Hi");
ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
verify(mockLibrary).foo(stringCaptor.capture());
String actualArgument = stringCaptor.getValue();
assertEquals(actualArgument, "Hi");
}

Mocking simple property access with JMockIt

I have a simple get-set interface:
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
This interface is a dependency of my actual class under test. I'm trying to mock out Foo to have this effective behavior:
public class MockedFoo implements Foo {
private String bazField;
#Override
public void setBaz(String baz) {
bazField = baz;
}
#Override
public String getProcessedBaz() {
return "PROCESSED_" + bazField;
}
}
So my expected result is:
mockedFoo.setBaz("ABC");
assertEquals("PROCESSED_ABC", mockedFoo.getProcessedBaz());
I was able to capture the method argument using withCapture in a Verification, but how do I set up an Expectation with that same input value? It seems you can do either one or the other.
Is there a way to express this in JMockIt? I'm using the latest version (1.9).
NOTE: I'm aware that I can simply set up a Mockup<Foo> instance and put in all the code above. However, my real code is much more complex and I would prefer not to hand-craft the entire mock class.
You can do this using Delegate. You may try this
Class to test
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
class FooSubClass implements Foo {
private String bazField;
#Override
public void setBaz(String baz) {
bazField = null;
}
#Override
public String getProcessedBaz() {
return bazField;
}
}
Test class
import mockit.Capturing;
import mockit.Deencapsulation;
import mockit.Delegate;
import mockit.NonStrictExpectations;
import org.junit.Before;
import org.junit.Test;
public class FooTest
{
FooSubClass fooSubClass;
#Capturing Foo fooMocked;
#Before
public void setUp()
{
fooSubClass = new FooSubClass();
}
#Test
public void testAMethod()
{
new NonStrictExpectations()
{
{
fooMocked.setBaz(anyString);
result = new Delegate()
{
void setBaz(String baz)
{
Deencapsulation.setField(fooSubClass, "bazField", baz);
}
};
times = 1;
fooMocked.getProcessedBaz();
result = new Delegate()
{
String getProcessedBaz()
{
return "PROCESSED_" + Deencapsulation.getField(fooSubClass, "bazField");
}
};
times = 1;
}
};
fooSubClass.setBaz("abc");
System.out.println(fooSubClass.getProcessedBaz());
}
}
NOTE: This was inspired by Varun's answer, but I wanted to avoid using reflection and intermediate classes. Rogério also provided a viable alternative, but it did not fit into the overall structure of my test. Thanks to both!
Here's how I finally got it working:
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
}
#RunWith(JMockit.class)
public class FooTest {
#Injectable
private Foo mockedFoo = null;
#Test
public void testBaz() {
new Expectations() {
private String bazState; // Variable inside Expectations stores the state between calls
{
mockedFoo.setBaz(anyString);
result = new Delegate() {
void setBaz(String baz) { bazState = baz; }
};
mockedFoo.getProcessedBaz();
result = new Delegate() {
String getProcessedBaz() { return "PROCESSED_" + bazState; }
};
}
};
mockedFoo.setBaz("ABC");
assertEquals("PROCESSED_ABC", mockedFoo.getProcessedBaz());
}
}
One way to write such an state-based test is:
public interface Foo {
void setBaz(String baz);
String getProcessedBaz();
void someOtherMethod();
}
public static class ClassUnderTest {
String doSomething(Foo foo) {
foo.setBaz("ABC");
foo.someOtherMethod();
return foo.getProcessedBaz();
}
}
#Test
public void mockFoo() {
Foo foo = new MockUp<Foo>() {
String baz;
#Mock void setBaz(String baz) { this.baz = baz; }
#Mock String getProcessedBaz() { return "PROCESSED_" + baz; }
}.getMockInstance();
String res = new ClassUnderTest().doSomething(foo);
assertEquals("PROCESSED_ABC", res);
}
An equivalent test can also be written with the JMockit Expectations API (using Delegate objects), but it would be more verbose as that API is meant for behavior-based testing (ie, when you care more about which methods get invoked than state-transfer between objects).

Running two same tests with different arguments

I have a test with 15-20 different test cases, I want to run the same test with twice with two different parameters which are supposed to be passed to the test's BeforeClass method, for instance:
public class TestOne {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument1", "Argument2");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here
}
public class TestTwo {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here, same as in TestOne
}
As you can see the only difference between these two tests is in the setup method, which passes different values to the constructor of the ClassToTest. I don't want to replicate the test methods in both classes, but would prefer either inheritance or some other intelligent way to achieve this in one class.
This seems like a perfect use case for JUnit4's #Parameters; see https://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit or http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ . That said, you'll have to move the initialization from the setUp method to a constructor for the test class.
For what it's worth, here is how you would do it with TestNG:
public class TestFactory {
#Factory
public Object[] createTests() {
return new Object[] {
new ClassToTest("arg1", "arg2"),
new ClassToTest("arg3", "arg4")
};
}
}
public class ClassToTest {
public ClassToTest(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
#Test
public void testOne() {
// use arg1 and arg2
}
}
Thanks all for your quick replies. This is how I did it finally
public abstract class Base {
final HeavyObject heavy;
protected Base(HeavyObject heavy) {
this.param = param;
}
#Test
public void test() {
param.doSomething();
}
#Test
.............More tests here
}
public class FirstTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg1", "arg2");
}
public FirstTest() {
super(param);
}
}
public class SecondTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg3", "arg4");
}
public FirstTest() {
super(param);
}
}
Base is an abstract class which has all the tests and FirstTest and SecondTest create their own objects with different parameters and pass it to the abstract class to use it.
As per the documentation (http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html):
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for
accessing its private fields, these can also be used by the subclass.
How about this:
public class TestOne {
private static ClassToTest classToTest1, classToTest2;
#BeforeClass
public static void setUp() throws Exception {
classToTest1 = new ClassToTest("Argument1", "Argument2");
classToTest2 = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
testOneImpl(classToTest1);
testOneImpl(classToTest2);
}
public void testOneImpl(ClassToTest classToTest) {
// exact samew as whatever your current testOne() test method is
}
....
}
EDIT:
Or to keep method count down:
public class TestOne {
private static List<ClassToTest> classesToTest;
#BeforeClass
public static void setUp() throws Exception {
classesToTest = new ArrayList<>;
classesToTest.add( new ClassToTest("Argument1", "Argument2"));
classesToTest.add( new ClassToTest("Argument3", "Argument4"));
}
#Test
public void testOne() {
for (ClassToTest classToTest: classesToTest) {
... same test content as before
}
}

Categories

Resources