Let's look at this piece of code :
public class A {
public void doSmth() { // pay attention - void method
// impl
}
}
public class B {
private A a_instance; // null
public void doSmthElse() {
a_instance.doSmth(); // NPE here without mock
// also do smth. else
}
}
Now, I have B b = new B(); and I want to test b.doSmthElse() , but I need to create a mock for a_instance object before, otherwise I will get NullPointerException ! How can I achieve this with EasyMock or PowerMock ???
#Test
public void testDoSomething()
{
// setup: sut
B b = new B();
A mockA = EasyMock.createMock(A.class);
b.setA_instance(mockA); // If you have a setter
// setup: expectations
mockA.doSmth();
// exercise
EasyMock.replay(mockA);
b.doSmthElse();
// verify
EasyMock.verify(mockA);
}
#Test
public void testDoSomething_setUsingReflection()
{
// setup: sut
B b = new B();
A mockA = EasyMock.createMock(A.class);
// Set the collaborator using a Spring reflection utility
ReflectionTestUtils.setField(b, "a_instance", mockA);
// setup: expectations
mockA.doSmth();
// exercise
EasyMock.replay(mockA);
b.doSmthElse();
// verify
EasyMock.verify(mockA);
}
You can use
instanceName.methodName();
Easymock.expectLastCall(); //for void methods this is how it is done
instanceName can be mocked or actualInstance.
If u can make the method static then it is easier with powermock
Powermock.mockStatic(ClassNameContainingStaticMethod)
All static methods get mocked directly
Word of Caution:- Converting a method to static can have issues in other parts.Do it carefully
Hope it helps.
All the best!
I don't see a reason why PowerMock is required here. You can achieve that with EasyMock itself.
#Test
public void testDoSmthElse() {
A a = EasyMock.createMock(A.class);
EasyMock.expect(a.doSmth()).andReturn(/*some value */);
EasyMock.replay(a);
B b = new B();
Object whatever = b.doSmthElse();
assert(); // psuedo-line. Add whatever assertion required
}
Note: Import appropriate classes
Related
I need to unit test a function, which makes an inner call of another void method.
Class TestClass {
public void testMethod() {
someOtherClass.testMethod(); // This is void method
}
}
I need to mock someOtherClass.testMethod() and then verify testMethod of TestClass using assert.
Sorry for my post if it is confusing. Let me make it more clear. My intention is -
public void testMethodTest() {
TestClass tC = new TestClass(); SomeOtherClass obj = EasyMock.createNiceMock(SomeOtherClass.class);
tC.set(obj);
obj.testMethod();
EasyMock.expectLastCall().andAnswer(new IAnswer() {
public Object answer() { // return the value to be returned by the method (null for void)
return null;
}
});
EasyMock.replay(obj);
tC.testMethod(); // How to verify this using assert.
}
What you wrote is working. However, it is overly complicated and you are not verifying that the void method was actually called. To do that, you need to add EasyMock.verify(obj); at the end.
Then, one important thing is that if you call a void method before the replay, it records a call. No need to add an expectLastCall. Also, you could have used expectLastCall().andVoid() instead of the IAnswer.
Here is how I would write it:
#Test
public void testMethodTest() {
TestClass tC = new TestClass();
SomeOtherClass obj = mock(SomeOtherClass.class); // no need to use a nice mock
tC.set(obj);
obj.testMethod();
replay(obj);
tC.testMethod();
verify(obj); // Verify testMethod was called
}
public Data extraMethod(Data data) // interface Data
{
Data d = Singleton.getInstance().sort(data.get() , "desc");
//do something, logical
return d;
}
How can I mock the object Data(the singleton extra return result), class Singleton has a static method getInstance and no public constructor. I want to test the logical part, test extraMethod without Data sort operation.
You could get away without PowerMock if you would spy your class under test and create a package level method that would be return the Singleton.
You still need to set-up what should happen when the sort method is invoked:
1) Class under test
public Data extraMethod(Data data) // interface Data
{
Data d = getSingleton().sort(data.get() , "desc");
//do something, logical
return d;
}
Singleton getSingleton(){
return Singleton.getInstance();
}
2) Test
#Spy
private MyClass myClassSpy = new MyClass();
#Mock
Singleton singletonStub;
#Mock
Data dataStub;
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception{
// Arrange
doReturn(singletonStub).when(myClassSpy).getSingleton();
when(dataStub.get()).thenReturn(...);
when(singletonStub.sort(any(Data.class), "desc")).thenReturn(/* some data*/);
// Act and Assert
}
My class structure is as follows:
public class MyParentClass {
void doSomethingParent() {
System.out.println("something in parent");
}
}
public class MyClass extends MyParentClass {
protected String createDummyRequest(Holder myHolder) {
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}
private void callingDB() {
System.out.println("Calling to DB");
}
}
Then my unit test:
public class UnitTest {
public void testCreateDummyRequest() {
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()
//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}
How do I prevent the calling of the super.doSomethingParent() in my method? (method which I am writing my test)
With this class structure mocking and testing is real hard. If possible, I'd advice to change the structure as in mist cases a class structure that's hard to mock and test is equally hard to extend and maintain.
So if you could change your class structure to something similar to:
public class MyClass {
private DoSomethingProvider doSomethingProvider;
private DbConnector dbConnector;
public MyClass (DoSomethingProvider p, DbConnector c) {
doSomethingProvicer = p;
dbConnector = c;
}
protected String createDummyRequest(Holder myHolder){
//...
doSomethingProvider.doSomethingParent();
//...
dbConnector.callingDB();
return "processedOutput";
}
}
Then you could easily create your instance with mocks of DoSomethingProvider and DbConnector and voila....
If you can't change your class structure you need to use Mockito.spy instead of Mockito.mock to stub specific method calls but use the real object.
public void testCreateDummyRequest(){
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.spy(new MyClass());
Mockito.doNothing().when(mockObj).doSomething();
mockObj.createDummyRequest(mockHolder);
}
Note: Using the super keyword prevents Mockito from stubbing that method call. I don't know if there is a way to stub calls to super. If possible (as in you didn't override the parent method in your class), just ommit the keyword.
I faced similar issue, so I find out that using spy() can hepld.
public class UnitTest {
private MyClass myObj;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
myObj= spy(new MyClass());
}
#Test
public void mockedSuperClassMethod(){
doNothing().when((MyParentClass )myObj).doSomethingParent();
//...
}
}
This approach works for me.
I found another approach, which turned out to be very useful in my case.
In the case I had, I needed to create a new class extending another, which included a very complex (legacy code) protected final method. Due to the complexity, it wasn't really possible to refactor to use composition, so here's what I came up with.
Let's say I have the following:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
class MyNewClass extends Parent {
#Override
public void implementMe() {
// custom stuff
doComplexStuff(/* a long parameter list */); // calling the parent
// some more custom stuff
}
}
Here's how I rearranged this code:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
interface ComplexStuffExecutor {
void executeComplexStuff(/* a long parameter list, matching the one from doComplexStuff */);
}
class MyNewClass extends Parent {
private final ComplexStuffExecutor complexStuffExecutor;
MyNewClass() {
this.complexStuffExecutor = this::doComplexStuff;
}
MyNewClass(ComplexStuffExecutor complexStuffExecutor) {
this.complexStuffExecutor = complexStuffExecutor;
}
#Override
public void implementMe() {
// custom stuff
complexStuffExecutor.doComplexStuff(/* a long parameter list */); // either calling the parent or the injected ComplexStuffExecutor
// some more custom stuff
}
}
When creating instance of MyNewClass for "production" purposes, I can use the default constructor.
When writing unit tests, however, I'd use the constructor, where I can inject ComplexStuffExecutor, provide a mock there and only test my custom logic from MyNewClass, i.e.:
class MyNewClassTest {
#Test
void testImplementMe() {
ComplexStuffExecutor complexStuffExecutor = Mockito.mock(ComplexStuffExecutor.class);
doNothing().when(complexStuffExecutor).executeComplexStuff(/* expected parameters */);
MyNewClass systemUnderTest = new MyNewClass(complexStuffExecutor);
// perform tests
}
}
At first glance, it seems like adding some boilerplate code just to make the code testable. However, I can also see it as an indicator of how the code should actually look like. Perhaps one day someone (who would find courage and budget ;) ) could refactor the code e.g. to implement the ComplexStuffExecutor with the logic from doComplexStuff from Parent, inject it into MyNewClass and get rid of inheritance.
Here is how it can be done
public class BaseController {
public void method() {
validate(); // I don't want to run this!
}
}
public class JDrivenController extends BaseController {
public void method(){
super.method()
load(); // I only want to test this!
}
}
#Test
public void testSave() {
JDrivenController spy = Mockito.spy(new JDrivenController());
// Prevent/stub logic in super.method()
Mockito.doNothing().when((BaseController)spy).validate();
// When
spy.method();
// Then
verify(spy).load();
}
Source: https://blog.jdriven.com/2013/05/mock-superclass-method-with-mockito/
I have a class as below:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
The logic in the constructor A(String test) and check() are the things I am trying to mock. I want any calls like: new A($$$any string$$$).check() returns a dummy string "test".
I tried:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
But it doesn't seem to be working. new A($$$any string$$$).check() is still going through the constructor logic instead of fetch the mocked object of A.
The code you posted works for me with the latest version of Mockito and Powermockito. Maybe you haven't prepared A?
Try this:
A.java
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
MockA.java
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
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 MockA {
#Test
public void test_not_mocked() throws Throwable {
assertThat(new A("random string").check(), equalTo("checked random string"));
}
#Test
public void test_mocked() throws Throwable {
A a = mock(A.class);
when(a.check()).thenReturn("test");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("random string").check(), equalTo("test"));
}
}
Both tests should pass with mockito 1.9.0, powermockito 1.4.12 and junit 4.8.2
To my knowledge, you can't mock constructors with mockito, only methods. But according to the wiki on the Mockito google code page there is a way to mock the constructor behavior by creating a method in your class which return a new instance of that class. then you can mock out that method. Below is an excerpt directly from the Mockito wiki:
Pattern 1 - using one-line methods for object creation
To use pattern 1 (testing a class called MyClass), you would replace a call like
Foo foo = new Foo( a, b, c );
with
Foo foo = makeFoo( a, b, c );
and write a one-line method
Foo makeFoo( A a, B b, C c ) {
return new Foo( a, b, c );
}
It's important that you don't include any logic in the method; just the one line that creates the
object. The reason for this is that the method itself is never going
to be unit tested.
When you come to test the class, the object that you test will
actually be a Mockito spy, with this method overridden, to return a
mock. What you're testing is therefore not the class itself, but a
very slightly modified version of it.
Your test class might contain members like
#Mock private Foo mockFoo;
private MyClass toTest = spy(new MyClass());
Lastly, inside your test method you mock out the call to
makeFoo with a line like
doReturn( mockFoo )
.when( toTest )
.makeFoo( any( A.class ), any( B.class ), any( C.class ));
You can use matchers that are more specific than any() if you want to
check the arguments that are passed to the constructor.
If you're just wanting to return a mocked object of your class I think this should work for you. In any case you can read more about mocking object creation here:
http://code.google.com/p/mockito/wiki/MockingObjectCreation
With Mockito you can use withSettings(). For example if the CounterService required 2 dependencies, you can pass them as a mock:
UserService userService = Mockito.mock(UserService.class);
SearchService searchService = Mockito.mock(SearchService.class);
CounterService counterService = Mockito.mock(CounterService.class, withSettings().useConstructor(userService, searchService));
Starting with version 3.5.0 of Mockito and using the InlineMockMaker, you can now mock object constructions:
try (MockedConstruction mocked = mockConstruction(A.class)) {
A a = new A();
when(a.check()).thenReturn("bar");
}
Inside the try-with-resources construct all object constructions are returning a mock.
Without Using Powermock .... See the example below based on Ben Glasser answer since it took me some time to figure it out ..hope that saves some times ...
Original Class :
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(new BClazz(cClazzObj, 10));
}
}
Modified Class :
#Slf4j
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(getBObject(cClazzObj, 10));
}
protected BClazz getBObject(CClazz cClazzObj, int i) {
return new BClazz(cClazzObj, 10);
}
}
Test Class
public class AClazzTest {
#InjectMocks
#Spy
private AClazz aClazzObj;
#Mock
private CClazz cClazzObj;
#Mock
private BClazz bClassObj;
#Before
public void setUp() throws Exception {
Mockito.doReturn(bClassObj)
.when(aClazzObj)
.getBObject(Mockito.eq(cClazzObj), Mockito.anyInt());
}
#Test
public void testConfigStrategy() {
aClazzObj.updateObject(cClazzObj);
Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj);
}
}
Mockito has limitations testing final, static, and private methods.
Alternate Solution:
with jMockit testing library, you can do few stuff very easy and straight-forward as below:
Mock constructor of a java.io.File class:
new MockUp<File>(){
#Mock
public void $init(String pathname){
System.out.println(pathname);
// or do whatever you want
}
};
the public constructor name should be replaced with $init
arguments and exceptions thrown remains same
return type should be defined as void
Mock a static method:
remove static from the method mock signature
method signature remains same otherwise
Using Mockito 4 (but I suspect this is true for Mockito from 3.5.0 version) you can mock the constructor and, in the initializer, you can assert the values of the parameters.
For example:
try (MockedConstruction<A> constr = mockConstruction(A.class,
(mock, context) -> {
if (context.getCount() == 1) {
assertArrayEquals(context.arguments().toArray(), new Object[] {"test"});
} else {
fail("No more calls should happen");
}
})) {
// Do the rest of assertions.
}
Notice that you need to put the MockedConstruction instantiation in a try-with-resources otherwise the mocked construction is leaked outside the test.
I'm writing a JUnit test and also using Mockito, and I want to call a method, which in turn calls a second method a number of times. I do not want that second method to ever be called during my unit test, but I want to know what it's arguments would have been. My code to be tested looks something like this:
public class MyClass {
public void myMethod() {
int a = [do some logic]
int b = [do some logic];
doSomething(a, b);
a = [do some logic];
b = [do some logic];
doSomething(a, b);
}
public void doSomething(int a, int b) {
// code that I do not want to be executed during a unit test
}
}
And now a unit test:
#Test
public void test() {
MyClass myClass = new MyClass();
myClass.myMethod();
verify(myClass).doSomething(17, 33);
verify(myClass).doSomething(9, 18);
}
I am new to Mockito and I don't know if it's possible to either A) prevent doSomething() from being executed and B) verify the values of the a & b arguments. I'm willing to accept answers like "Mockito cannot help you here" or "this is not something that is technically possible." If there's no way to mock this sort of thing, I may consider refactoring those [do some logic] blocks into methods that I can test directly but my code is more complex than this simple example, and I am not allowed to post the code online.
Spies are ugly. If you partially mock your class under test, you easily to get confused about what is mocked and what is really tested. Mockito's Javadoc explicitly warns against partial mocking.
Better to refactor your code so you can test it cleanly. Extract doSomething() into a new class:
public class SomethingDoer {
public void doSomething(int a, int b) {
// code that you do not want to be executed during a unit test
}
}
Changed MyClass:
public class MyClass {
private final SomethingDoer somethingDoer;
public MyClass(SomethingDoer somethingDoer) {
this.somethingDoer = somethingDoer;
}
public void myMethod() {
int a = [do some logic]
int b = [do some logic];
somethingDoer.doSomething(a, b);
a = [do some logic];
b = [do some logic];
somethingDoer.doSomething(a, b);
}
}
Test:
#Test
public void test() {
SomethingDoer somethingDoer = mock(SomethingDoer.class);
MyClass myClass = new MyClass(somethingDoer);
myClass.myMethod();
verify(somethingDoer).doSomething(17, 33);
verify(somethingDoer).doSomething(9, 18);
}
To do this, you need a Mockito partial mock.
This is untested, but I think what you want might be something along the lines of:
#Test
public void test() {
MyClass myClass = spy(new MyClass());
doNothing().when(myClass).doSomething(any(Integer.class), any(Integer.class));
myClass.myMethod();
verify(myClass).doSomething(17, 33);
verify(myClass).doSomething(9, 18);
}
The spy sets up a partial mock, so that you can replace some methods and use some real methods. The doNothing stubs your doSomething (an interesting naming coincidence) to do nothing instead of calling the real code.