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
}
Related
public class MainClass {
public void method1() {
…….
String str = getMethod2();
method3(str);
}
protected String getMethod2() {
String str = “Actual Value”
return str;
}
private void method3(String strparam) {
……
}
}
#RunWith(MockitoJunitRunner.class)
public class Testclass {
#InjectMocks
MainClass obj = new MainClass();
……
#Test
public void testSpy() {
MainClass spyMain = spy(obj);
when(spyMain.getMethod2()).thenReturn(new String("Testing spy"));
obj.method1();
……..
}
}
Want to use a new value returned from getMethod2() from test as it’ll be passed to method3.
I was under the impression that the call to method1 from test class calls method2 and I thought the value retuned from method2 is “Testing spy” but is “Actual Value” and the “Actual Value” is passed to method3 when test class is ran.
How to use the new value from test class?
You are calling the method on obj (obj.method1();), instead of on the object that you've spied: spyMain.method1();.
Assuming the code in your example is actually java code and the capitalization was added when you copied it into Microsoft Word (or some other word processor),
try this:
public void testSpy()
{
MainClass spyMain = spy(obj);
doReturn("Blammy").when(spyMain).getMethod2();
obj.method1();
}
Here are some more info:
The test class must be in the same package as the MainClass.
For example:
Location of MainClass: src/main/java/blammy/MainClass.java
Location of TestClass: src/test/java/blammy/TestClass.java
The doReturn variation of mocking does not call the wrapped method,
but the thenReturn variation does.
This is wrong:
#InjectMocks
MainClass obj = new MainClass();
Only use the #InjectMocks annotation if you are calling MockitoAnnotations.initMocks(class).
Here is your test class rewritten to use #InjectMocks
#RunWith(MockitoJunitRunner.class)
public class Testclass
{
#InjectMocks
private MainClass classToTest;
#Before
public void beforeTest()
{
MockitoAnnotations.initMocks(this)
}
#Test
public void testSpy()
{
spyClassToTest = spy(classToTest);
doReturn("Testing spy").when(spyClassToTest ).getMethod2();
spyClassToTest.method1();
}
}
More Notes:
You may be able to use #Spy and #InjectMocks on the same object
(in my example, on classToTest),
but I never do that.
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 am trying to do the follow (Im sure there is a way, but I cant figure it out).
The problem:
There is a private method in my class, the class was injected using #InjectedMocks.
The private method calls a service and sends as parameter a property from a privated object.
Something like this
private MyObject myObject = new Object();
public void main(){
doSomething();
}
private void doSomething(){
someService(mObject.getValue);
}
The problem is that my object is not that easy and it has an annotation that gives it the value. Seems like with #InjectedMocks the value is never assigned and myObject is always null.
Since both the method and the object are private I cannot just assign the value (And I am avoiding add public setters for them).
My approach:
I want to mock something like this:
when(any(MyObject).class).getValue().thenReturn("something");
So, I will avoid NP at my test.
Is it possible using mockito?
Is there any more elegant way to do this??
I assume that you have some errors in your code example.
The following actually works and prints "foobar": try to compare it with your actual code to see what you forgot.
public class MockitoTest {
#InjectMocks private TestClass test;
#Mock private MyObject mock;
#Test
public void test() {
MockitoAnnotations.initMocks(this);
Mockito.when(mock.getValue()).thenReturn("foobar");
test.main();
}
}
class TestClass {
private MyObject myObject = new MyObject();
public void main() {
doSomething();
}
private void doSomething() {
System.out.println(myObject.getValue());
}
}
class MyObject {
public String getValue() {
return "hello";
}
}
You can mock the object or the method alone using PowerMock.createPartialMock and the proxy the method call.
For example your above code
when(any(MyObject).class).getValue().thenReturn("something");
should be
when(mockedObject).methodCall().thenReturn("something");
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 am recently working on TDD with JUnit and Mockito. For some purpose within a method, I am using an Util class (an utility class having methods in project context). The thing is what I am facing is how to mock such classes in Mockito. I am not able to find as such implementation regarding static methods in Mockito. Some suggest using PowerMock on top of Mockito but wouldn't that replace my JunitMockitoRunner?
The way I am using the static function is:
public void doSomething(int x){
//Some code
Y y = Util.someStaticMethod(x);
//Some more code
}
EDIT : Also I read somewhere that using static methods is a code smell and is a sign of bad design. So how should I be refactoring the design and what advantages will I be having as a result?
How should I be refactoring the design and what advantages will I be having as a result?
Well, if you need to mock the static utility method, then make it an instance method of an injectable object, so that you can inject a mock implementation of this object. The advantage is that it makes your code more testable:
public class Util {
public Y someInstanceMethod(X x) {
...
}
}
public class ClassToBeTested {
private Util util;
public ClassToBeTested(Util util) {
this.util = util;
}
public void doSomething(int x){
//Some code
Y y = util.someInstanceMethod(x);
//Some more code
}
}
public class ClassToBeTestedTest {
public void testDoSomething() {
Util mockUtil = mock(Util.class);
ClassToBeTested t = new ClassToBeTested(mockUtil);
when(mockUtil.someInstanceMethd(3)).thenReturn(...);
...
}
}
That's the main selling point of dependency injection: it makes your code testable.
I do something like that for mocking static Util classes with jMockit.
public class UtilsTest {
#After
public void teardown() {
Mockit.restoreAllOriginalDefinitions();
}
#Test
public void testMyUtil() {
Mockit.setUpMocks( MockUtil.class );
}
}
#MockClass(realClass=Util.class)
public class MockUtil{
#Mock
public static MySpecialClass someStaticMethod(int x) {
return Mockito.mock(MySpecialClass.class);
}
}