I'm trying to use JMockit in order to mock a protected method of a class:
public class A {
protected String say() {
return "hi";
}
}
public class B extends A {
public String cry() {
return "waaaa " + say();
}
}
I want to mock "say" method in my tests, so that every instance of B, when it invokes "say", it will get "bye" instead of "hi".
Thanks.
You can simply make a MockUp of A:
new MockUp<A> () {
#Mock protected String say() { return "bye"; }
};
System.out.println(new B().cry()); // prints waaaa bye
Related
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);
}
}
I have a singleton class S which implements an interface I.
Singleton class has a method A which inturn calls method B.
I have to test method A.
This is my singleton Class
public class S implements I{
private static S INSTANCE = new S();
public static I getInstance(){
return INSTANCE;
}
public String methodA(){
methodB();
}
}
This is how my method looks in the test class.
public void testMethodA(){
S so = S.getInstance();
S spy = Mockito.spy(so);
Mockito.doReturn(something).when(spy).methodB(); // I have to cut the dependency of this method B, hence will stub this
String exp_value = 'X';
assertEquals(exp_value,spy.methodA);
}
The issue is, actual method B is called instsead of the stub and hence my test fails.
Could anyone help and let me know if im doing anything wrong here.
Your code with a few modifications compiles and runs as expected. Here is a self contained running example.
public class StackOverflow59960713 {
public interface I {
String methodA();
}
public static class S implements I {
private static S INSTANCE = new S();
public static I getInstance() {
return INSTANCE;
}
public String methodA() {
return methodB();
}
public String methodB() {
return "abc";
}
}
#Test
public void testMethodA() {
S so = (S) S.getInstance(); <== getInstance() returns I not S
S spy = Mockito.spy(so);
Mockito.doReturn("123").when(spy).methodB();
String exp_value = "123";
assertEquals(exp_value, spy.methodA()); <=== methodA() not methodA
}
}
I would like to add additional implementation to an overriding subclass method without completely overriding the superclass one. This is what I got to so far, but it doesn't seem to work. I would like the output to be "superclass return" followed by "subclass return". Here's the code:
public class A {
public String send() {
return "superclass return";
}
}
public class B extends A{
public String send() {
super.send();
return "subclass return";
}
}
public class Driver {
public static void main(String[] args) {
B b = new B();
System.out.println(b.send());
}
}
Output: subclass return
Am I using the wrong syntax super.send()? The intended output should be:
superclass return
subclass return
You have lost the return value of the super send() method and that is why you cannot see it in the output. To be able to see both, you need to modify the child implementation to something like this:
public String send() {
String value = super.send();
return value + "subclass return";
}
You aren't doing anything with the return value of the super class. Try this:
public class A {
public String send() {
return "superclass return";
}
}
public class B extends A{
public String send() {
return super.send() + "subclass return";
}
}
public class Driver {
public static void main(String[] args) {
B b = new B();
System.out.println(b.send());
}
}
Or if you want the line break:
return super.send() + "\nsubclass return";
i have such java codes:
public class A {
public int get() {
// many codes
String s = new String();
//...
int n = 5;
return isEmpty(s) ? n : -1;
}
public boolean isEmpty(String s) {
return s.isEmpty();
}
}
now i want to just test get(), i don't want to test isEmpty() at the same, so i want to mock isEmpty(), just test a method, if it invokes another method of the class, can easymock mock the method?
A workable approach is to not mock A and do something like
public class TestableA extends A
{
#Override
public boolean isEmpty( String s )
{
// "mock" impl goes here, eg.:
return s;
}
}
and write your unit test in terms of TestableA instead. You can even create this in a #Before method:
public class UnitTest
{
private A a; // note: A, not TestableA!
#Before
public void setUp()
{
this.a = new A()
{
#Override
public boolean isEmpty( String s )
...
}
}
#Test
...
}
I'm having problems with counting method calls with Mockito. Problem is that the method whos calls I want to count is called in test class indirectly by other method. Here is the code:
public class ClassForTest {
private Integer value;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
And the test class:
public class ClassForTestTest extends TestCase {
#Test
public void testDoSmth() {
ClassForTest testMock = mock(ClassForTest.class);
doNothing().when(testMock).prepareValue(anyString());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
}
Having such exception:
Wanted but not invoked:
classForTest.prepareValue(<any>);
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:24)
However, there were other interactions with this mock:
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:21)
Any ideas please. Thanks in advance!
This will work. Using a spy calls the underlying method. Make sure value is initialized first.
#Test
public void testDoSmth() {
ClassForTest testMock = spy(new ClassForTest());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private Integer value = 0;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
This is an indication that you need some refactoring to improve your design. A single class should be fully testable without needing to mock out pieces of it. Whatever pieces you feel need to be mocked out should be extracted into one or more collaborating objects. Don't fall into the trap of partial mocks. Listen to what the tests are telling you. Your future self will thank you.
You are mocking the tested class. Mocking is intended for the dependencies of a tested class, rather than the class itself.
I suspect what you want is Mockito.spy(). However, this is partial mocking which the Mockito Javadoc recommends against.
Alternatively, if you want to refactor for testability, you can do the following:
#Test
public void testDoSmth() {
Preparer preparer = mock(Preparer.class);
ClassForTest cft = new ClassForTest(preparer);
cft.doSmth();
verify(preparer, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private final Preparer preparer;
public ClassForTest(Preparer preparer) {
this.preparer = preparer;
}
public void doSmth() {
preparer.prepareValue("First call");
preparer.prepareValue("Second call");
preparer.prepareValue("Third call");
System.out.println(preparer.getValue());
}
}
public class Preparer {
private Integer value = 0;
public void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
public Integer getValue() {
return value;
}
}