Lets say I have the following code:
Mocked object class
public class SomeClass {
private Foo someField;
public SomeClass {
someField = new Foo();
}
public Foo getSomeField { return someField; }
public void getSomething() {}
public boolean doSomething(Object object) {}
}
Next I have test suite
public class TestSuite {
private ClassToTest classToTest;
private SomeClass mock;
#Before
public void setUp() {
classToTest = new ClassToTest();
mock = EasyMock.createMock(SomeClass.class);
}
#Test
public void testMethod() throws Exception {
mock.getSomething();
EasyMock.replay(mock);
classToTest.methodToTest(mock); //Where methodToTest accepts SomeClass and int
EasyMock.verify(mock);
}
}
And method which is being tested
public void methodToTest(SomeClass a) {
//Logic here
Foo b = a.getSomeField();
b.do(); // <--- null pointer exception here because someField isn't initialized
a.getSomething(); // <--- thing I want to test if it is being called, but can't due to exception prior to this line
//Logic after
}
I am stuck.. So yea basically SomeClass isn't initialized like I wanted to. Is there any workaround? Or maybe any other frameworks which can do something like that?
Your methodToTest calls a.getSomeField(), but the setup part of your test doesn't expect that call. You want something like:
Foo foo = new Foo();
EasyMock.expect(mock.getSomeField()).andReturn(foo);
Or to stub the call:
Foo foo = new Foo();
EasyMock.expect(mock.getSomeField()).andStubReturn(foo);
(before your call to mock.getSomething()).
See this question for the differences between andReturn and andStubReturn.
Related
using Spring 2.0.3.RELEASE, JUnit Jupiter 5.7.0, Mockito 3.3.3
try to test method method01 of class Class01:
public class Class01 {
private RestConnector con;
public Class01(){
con = RestConnector.getInstance();
}
public Response method01(String x) {
Class01 example = new Class01();
String x = example.isAuthenticated();
// more stuff after this
}
public String isAuthenticated() throws IOException {
// I do stuff
return "a string";
}
}
In the test class have tried
public class Class01Test{
#Mock private Class01 class01Mock;
#Spy #InjectMocks private Class01 class01;
#Test
public void test() throws Throwable {
doReturn("I returned").when(class01). ??? stuck here .. always goes into the isAuthenticated method
Response result = class01.method01("a string");
}
}
Currently the test is always running the real method isAuthenticated.
How to setup a mock for the field example in method method01 so that the execute skips going into method isAuthenticated?
try to test method method01 of class Class01
Then you don't need mocks.
#Test
public void test() throws Throwable {
Class01 c = new Class01();
Response expected = ... ;
assertEquals(c.method01("input"), expected);
}
If you want to inject behaviour into example variable, you need to move it to a field
public class Class01 {
private RestConnector con;
private Class01 inner;
public Class01(){
con = RestConnector.getInstance();
}
Class01(Class01 c) {
this();
this.inner = c;
}
public Response method01(String x) {
String x = inner.isAuthenticated();
// more stuff after this
}
Along with a Mock
#RunWith(MockitoJunitRunner.class)
public class Class01Test{
#Mock Class01 class01Mock;
#Test
public void test() throws Throwable {
Response expected = ... ;
when(class01Mock.isAuthenticated()).thenReture(expected); ... // TODO: Setup
Class01 c = new Class01(class01Mock); // pass in the mock
assertEquals(c.method01("input"), expected);
}
However, unclear why you need a nested object of the same class when you appear to only need this.isAuthenticated()
Ideally, you'd also mock the RestConnector
I have a class in which I would like to verify method calls
Here is a representation of my class :
public class MyClass {
public void method1(String id) {
MyClass inst = this.getParticularInstance(id);
if(inst != null) {
inst.doSomething();
}
}
public MyClass getParticularInstance(String id) {
// return a particular object or null
}
public void doSomething(String id) {
// do something
}
}
In particular, I would like to make sure that when I call method1, getParticularInstance is called, and depending of the result, doSomething is called or not.
Is it possible to test such a code with Mockito, and if yes is it the right way ?
Thank you
Spy the MyClass and use verify() to verify the method invocation
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
private MyClass myClass;
#Before
public void setUp() {
myClass = spy(new MyClass());
}
public void testMethod1() {
// Arrange
String id = "id1";
// Act
myClass.method1(id);
// Assert
verify(myClass).getParticularInstance(id);
}
}
Say, there's the following class to be tested:
public class MyClass {
public void method1() {
...
String str = method3()
...
}
public int method2() {...}
private String method3() {...}
}
I'm writing MyClassTest.java with JUnit. I want method3() to return a value that I have assigned, not execute the method itself. I can only use Mockito.
Is it possible?
If yes, how do I do it?
With just Mockito you cannot mock a private method.
But you could refactor your code to extract method3() in another class as a public method that you could use as dependency of MyClass. In this way method3() is naturally mockable.
public class MyClass {
private Foo foo;
public MyClass(Foo foo){
this.foo = foo;
}
public void method1() {
...
String str = foo.method3()
...
}
public int method2() {...}
}
public class Foo {
public String method3() {...}
}
Now mock that in the unit test :
#Mock
Foo fooMock;
MyClass myClass;
#BeforeEach
void init(){
myClass = new MyClass(fooMock);
}
#Test
public void method1(){
Mockito.when(fooMock.method3()).thenReturn("dummy value");
// call method1()
// do assertions
}
You can't do it with Mockito, but you can with JMockit. Your test would look like this:
#RunWith(JMockit.class)
public class JMockitTest {
#Tested
private MyClass myClass;
#Before
public void setUp(){
myClass = new MyClass();
}
#Test
public void testMethod1(){
new MockUp<MyClass>() {
#Mock
String method3() {
return "dummy value";
}
};
myClass.method1();
// do assertions
}
}
You can read the documentation about this feature, called faking, here.
I want mocked object return different values on each its method call. But the method has no parameter. Here is an example:
public class MyClass {
public double getValue() {
return 0;
}
}
public class IteratorClass {
MyClass myClass;
public IteratorClass(MyClass myClass) {
this.myClass = myClass;
}
public void iterate() {
for (int i = 0; i < 5; i++) {
System.out.println("myClass.getValue() = " + myClass.getValue());
}
}
}
public class IteratorClassTest {
private MyClass myClass;
private IteratorClass iteratorClass;
#Before
public void setUp() throws Exception {
myClass = mock(MyClass.class);
iteratorClass = spy(new IteratorClass(myClass));
}
#Test
public void testIterate() throws Exception {
when(myClass.getValue()).thenReturn(10d);
when(myClass.getValue()).thenReturn(20d);
when(myClass.getValue()).thenReturn(30d);
when(myClass.getValue()).thenReturn(40d);
when(myClass.getValue()).thenReturn(50d);
iteratorClass.iterate();
}
}
I'm spying here an IteratorClass and mocking MyClass. I want getValue() method return different value on each call. But it is returning last value set on mocked object. If getValue() method has some parameter like getValue(int arg), then could return different value according to the parameter. (e.g. getValue(0) -> return 10, getValue(1) -> return 20 etc).
But how to be when method has no parameters?
You can either specify the consecutive return values as chained method calls (aka fluent API):
#Test
public void testIterate() throws Exception {
when(myClass.getValue()).thenReturn(10d)
.thenReturn(20d)
.thenReturn(30d)
.thenReturn(40d)
.thenReturn(50d);
iteratorClass.iterate();
}
or as VarAgs:
#Test
public void testIterate() throws Exception {
when(myClass.getValue()).thenReturn(10d,20d,30d,40d,50d);
iteratorClass.iterate();
}
either way that last one will be retuned for any further call to the method.
According to answer from Using Mockito with multiple calls to the same method with the same arguments you should modify your code:
...
#Test
public void testIterate() throws Exception {
when(myClass.getValue()).thenReturn(10d, 20d, 30d, 40d, 50d);
iteratorClass.iterate();
}
...
I have a class to be tested which is like this:
public class MainClass extends BaseClass {
public static int variableToBeAsserted= 0;
MainClass(ConfigClass config) {
super(config);
}
public void myMethod() {
List list = objectOfClass1inSuperClass.operation(objectOfClass2inSuperClass.method())
while(methodInSuperClass()) {
// doing operations with 'list'
variableToBeAsserted++;
}
}
// ..few other methods which I am not going to test.
}
I have suppressed the constructor of my BaseClass and my ConfigClass. Now my test class is like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class TestClass {
#Before
public void setUp(){
suppress(constructor(BaseClass.class))
suppress(constructor(ConfigClass.class))
}
#Test
public void testMyMethod(){
MainClass main = new MainClass(new ConfigClass(""));
List list1= new ArrayList();
test1.add("somevalues");
Class1inSuperClass ob1 = PowerMock.createMock(Class1inSuperClass.class);
Class2inSuperClass ob2 = PowerMock.createMock(Class2inSuperClass.class);
EasyMock.expect(ob2.method()).andReturn(getClass());
EasyMock.expect(ob1.operation(getClass())).andReturn(list1);
PowerMock.replayAll();
main.myMethod();
Assert.assertEquals(expectedValue, main.variableToBeAsserted);
}
}
Now I don't know why but my test case fails with a NullPointerException.
It tries to access objectofClass1inSuperClass and fails. I thought this will mock it. But it does not get mocked.
EDIT: I am writing only the test and I cannot change anything in BaseClass. However I have the option to modify the MainClass.
You have two ways to inject mock object to the object under the test.
Manually via WhiteBox
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class WhiteBoxApproachTestClass {
#Before
public void setUp() throws Exception {
suppress(constructor(BaseClass.class));
}
#Test
public void testMyMethod() {
MainClass main = new MainClass(createMock(ConfigClass.class));
List<String> list1 = new ArrayList<>();
list1.add("somevalues");
Class1inSuperClass ob1 = createMock(Class1inSuperClass.class);
Class2inSuperClass ob2 = createMock(Class2inSuperClass.class);
expect(ob2.method()).andReturn(getClass());
expect(ob1.operation(getClass())).andReturn(list1);
Whitebox.setInternalState(main, "objectOfClass1inSuperClass", ob1);
Whitebox.setInternalState(main, "objectOfClass2inSuperClass", ob2);
replayAll();
main.myMethod();
assertThat(MainClass.variableToBeAsserted).isEqualTo(5);
}
}
And via #TestSubject (http://easymock.org/user-guide.html#mocking-annotations)
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class TestSubjectApproachTestClass {
#Mock(fieldName = "objectOfClass1inSuperClass")
private Class1inSuperClass ob1;
#Mock(fieldName = "objectOfClass2inSuperClass")
private Class2inSuperClass ob2;
#TestSubject
private final MainClass main = new MainClass(createMock(ConfigClass.class));
#BeforeClass
public static void before() throws Exception {
suppress(constructor(BaseClass.class));
}
#Test
public void testMyMethod() {
List<String> list1= new ArrayList<>();
list1.add("somevalues");
expect(ob2.method()).andReturn(getClass());
expect(ob1.operation(getClass())).andReturn(list1);
EasyMockSupport.injectMocks(main);
replayAll();
main.myMethod();
assertThat(MainClass.variableToBeAsserted).isEqualTo(5);
}
}
Full code you may find here.