I'm testing a class and wanted to monitor calls to a specific method, namely to save the calling parameters for later analysis.
Testing is done with EasyMock, so it was logical to use EasyMock.capture feature. However, the examples that I managed to find do not work for me - I get the following compile error at the line with capture:
expect(T) in EasyMock cannot be applied to (void)
reason: no instance of type variable T exist so that void conforms to T
It would be great if somebody could point out my mistake(s) for me. Below is a code snippet:
import static org.easymock.EasyMock.capture;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.EasyMock;
import org.junit.Before;
class B {
}
class A {
public void doSomething(B input) {
}
}
public class ATest {
private Capture<B> capturedData;
private A testObject;
#Before
private void setUp() {
capturedData = EasyMock.newCapture(CaptureType.ALL);
testObject = EasyMock.createNiceMock(A.class);
EasyMock
.expect(testObject.doSomething(capture(capturedData)))
.anyTimes();
}
}
Thanks a lot in advance!
Your problem is not related to the capture, but to the return type of your doSomething() method:
Since A.doSomething(B input) is of return type void, you don't expect the method to return anything, thus you cannot use EasyMock.expect() for it. Instead, simply invoke the method and use EasyMock.expectLastCall(), like so:
testObject.doSomething(capture(capturedData));
EasyMock.expectLastCall().anyTimes();
EasyMock.expectLastCall() declares that you expect the last method invocation before expectLastCall() to be executed. You can then handle it just like expect(), e.g. add anyTimes() to it.
Related
I am attempting to test a method that creates a new instance of another class that I wish to mock using powermock. My code (simplified) is as follows -
Testing code:
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.anyObject;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest {
private ClassToBeMocked classToBeMocked;
private ClassUnderTest classUnderTest;
public void testSimple() throws Exception {
classToBeMocked = createMock(ClassToBeMocked.class);
// trying to intercept the constructor
// I *think* this is the root cause of the issue
expectNew(ClassToBeMocked.class, anyObject(), anyObject(), anyObject()).andReturn(classToBeMocked);
classToBeMocked.close();
expectLastCall();
replayAll();
// call to perform the test
classUnderTest.doStuff();
}
}
Code that is being tested:
import ClassToBeMocked;
public class ClassUnderTest {
private ClassToBeMocked classToBeMocked;
public void doStuff() {
classToBeMocked = new ClassToBeMocked("A","B","C");
// doing lots of other things here that I feel are irrelevant
classToBeMocked.close();
}
}
Code that I wish to mock:
public class ClassToBeMocked {
public ClassToBeMocked(String A, String B, String C) {
// irrelevant
}
public close() {
// irrelevant
}
}
The error I get is as below:
java.lang.ExceptionInInitializerError
at ....more inner details of where this goes into
at ClassToBeMocked.close
at ClassUnderTest.doStuff
at TestForClassUnderTest.test.unit.testSimple
Caused by: java.lang.NullPointerException
PowerMock version:1.4.5
EasyMock version: 3.1
PS: I have stripped down the code to bare minimums, only showing the details of the mocking library, let me know if you think my other code is somehow interfering and I can give more details on the bits you think are important to show. Any links to other examples doing this may even help.
I realized that the reason this wasn't working was because I was extending another class. I had
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest extends AnotherClass {
}
as soon as I removed the extends, it worked. Not sure if its just not able to extend another class with powermock or due to AnotherClass, but removing it worked for me
whenever you wish to mock a new instance of any class, you should be doing like this
Powermock.expectNew(ClassYouWishToMock.class).andReturn(whateverYouWantToReturn).anyTimes();
Powermock.replayAll();
this will return 'whateverYouWantToReturn' whener new is called on this class.
but whenever you want to mock a instance variable, you should be using Whitebox feature of easymock.
have a look at following Example
Class A{
private B b;
}
to mock this my test class will look something like this
...//other powermock, easymock class level annotations
#PrepareForTest(B.class)
class ATest{
Whitebox.setInternalState(B.class,b,whateverValueYouWantYourMockedObjectToReflect);
}
here 'b' passed in parameter, is the variable name you want to mock.
Good Luck!
I have, for example, this class:
public class A {
private List<String> list;
public A(B b){
list = b.getList();
}
public List<String> someMethod(){
return list;
}
}
I want to unit test someMethod without invoking constructor. I use reflection to set list.
The problem is that I don't want to create B class object and I cannot mock it since it will cause NPE.
So my question is:
How to test someMethod without calling constructor of A? Is there any way to mock class A and doesn't lose posibility to call methods?
Creating constructor with zero arguments is not a solution.
Note: I don't want to change any part of A class. I'm asking if it is possible to perform this test without adding or changing anything in A class.
You can test class A without calling it's constructor by Mockito. Not sure if I really understand your requirement but the following codes work for me.
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ATest {
#Test
public void test() {
A a = mock(A.class);
when(a.someMethod()).thenCallRealMethod();
List<String> listInA = new ArrayList<String>();
ReflectionTestUtils.setField(a, "list", listInA);
assertThat(a.someMethod(), is(listInA));
}
}
You should mock out the collaborators to your class -- that means that you can create an instance of the class being tested, and pass in mocks, configured to 'do the right thing' when it's methods are called.
In your example, you want to create a mock B, and use it like this:
#RunWith(MockitoJUnitRunner.class)
class myTest {
#Mock private B b;
public void someMethod() {
doReturn(new ArrayList<String>()).when(b).getList();
A a = new A(b);
assertEquals("result", a.someMethod().get(0));
}
}
I don't want to create B class object
Add a constructor or factory method which doesn't require a B.
public A(B b){
this(b.getList());
}
/* package local */ A(List<String> list){
this.list = list;
}
By making the constructor package local it can be accessed by unit tests in the same package.
How to test someMethod without calling constructor of A?
You can use
A a = theUnsafe.allocateInstance(A.class);
but this is not recommended unless you have no other option e.g. deserialization.
So I'm sure there is something like this out there but I have been searching for an hour and haven't found exactly what I am looking for. say I have a class that looks like this:
public class MyClass
{
public void myMethod(boolean shouldCallOtherMethod)
{
if(shouldCallOtherMethod)
{
otherMethod();
}
}
public void otherMethod()
{
System.out.println("Called");
}
}
How do I make something like this work?
#Test
public void shouldCallMethod()
{
MyClass myClass = new MyClass();
myClass.myMethod(true)
// verify myClass.otherMethod method was called
}
Using Mockito, you can do spying on real objects like this:
import org.junit.Test;
import static org.mockito.Mockito.*;
public class MyClassTest {
#Test
public void otherMethodShouldBeCalled() {
MyClass myClass = new MyClass();
MyClass spy = spy(myClass);
spy.myMethod(true);
verify(spy).otherMethod();
}
}
There are some gotchas, so take a look at the relevant documentation as well.
Suppose MokeysClass has a constructor declared like this, where Foo is some other class.
public MokeysClass(String name, int counter, Foo myFoo)
I would write my test like this.
#RunWith(MockitoJUnitRunner.class)
public class TestArray {
#Mock
private Foo mockMyFoo;
private String nameToInject = "Mokey";
private int counterToInject = 42;
#Spy
private MokeysClass toTest = new MokeysClass(nameToInject, counterToInject, mockMyFoo);
#Test
public void shouldCallMethod() {
toTest.myMethod(true);
verify(toTest).otherMethod();
}
}
so that I am explicitly stating which constructor to call when I create my test object, and what arguments to pass to it.
There are some reasons not to rely on #InjectMocks to do this step for me, particularly if the class being tested is more complex and has more than one constructor. Mockito chooses the constructor that has the most arguments, but if there are several constructors with the same number of arguments, Mockito could choose any of the constructors; that is, the behaviour is undefined.
Once Mockito has chosen a constructor, it checks whether that constructor can in fact be used for constructor injection. Constructor injection will not be used if
one or more of the parameters of the chosen constructor is a primitive type,
the type of one or more of the parameters of the chosen constructor is a final class,
the type of one or more of the parameters of the chosen constructor is a private class,
the only constructor of the class is the default constructor.
If any one of these conditions holds, for the constructor that Mockito chose, then constructor injection won’t be used. In this case, the class must have a default constructor, otherwise Mockito will throw an exception.
The complexity of the criteria which Mockito uses when choosing whether to apply constructor injection implies that adding or removing a constructor, or changing the parameters of a constructor, can make Mockito switch from using constructor injection to using setter and field injection; or from using setter and field injection to using constructor injection. This can occur even if the constructor that is changed is not the one that will be used for constructor injection.
As a result, any test that uses constructor injection is automatically quite brittle; in the sense that changes that are not directly related to the test itself can cause the test to fail. Such failures can be difficult to troubleshoot.
The #InjectMocks annotation was designed for use with frameworks such as Spring that do dependency injection; and for tests of classes that use Spring, it can be invaluable. But if dependency injection is not part of your class, I would strongly recommend avoiding #InjectMocks on account of its brittleness. You really want your test code to be as easy to maintain and to troubleshoot as your production code is.
This is not recommended, but you can spy real object :)
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.BDDMockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Spy
private MyClass sut; // System Under Test
#Test
public void shouldCallMethod() {
// when
sut.myMethod(true);
// then
verify(sut).otherMethod();
}
}
Result:
Tests Passed: 1 passed in 0,203 s
After changing code: sut.myMethod(false);
Wanted but not invoked:
sut.otherMethod();
-> at my.custom.MyClassTest.shouldCallMethod(MyClassTest.java:23)
Source: Spying on real objects
Magic version with constructor injection
#Mock
private LexAnalyzer lexAnalyzer;
#Spy
#InjectMocks
private SyntaxAnalyzer sut; // System Under Test
#Test
public void shouldCallMethod() {
// when
sut.myMethod(true);
// then
verify(sut).otherMethod();
}
SyntaxAnalyzer.java
public class SyntaxAnalyzer {
private final LexAnalyzer lexAnalyzer;
public SyntaxAnalyzer(LexAnalyzer lexAnalyzer) {
this.lexAnalyzer = lexAnalyzer;
}
...
Tested, works ;)
I think you want to look at Mock objects. You can create a mock of MyClass, then set expectations that otherMethod() is called when you call myMethod and fails if it was not called.
Here is a pretty good overview of them for java - http://www.scalatest.org/user_guide/testing_with_mock_objects
One other major benefit of using Mocks, you can avoid side affects, like logging to NSLog or hitting a web server or printing) in your test.
How to verify that a method is not called on an object's dependency?
For example:
public interface Dependency {
void someMethod();
}
public class Foo {
public bar(final Dependency d) {
...
}
}
With the Foo test:
public class FooTest {
#Test
public void dependencyIsNotCalled() {
final Foo foo = new Foo(...);
final Dependency dependency = mock(Dependency.class);
foo.bar(dependency);
**// verify here that someMethod was not called??**
}
}
Even more meaningful :
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
// ...
verify(dependency, never()).someMethod();
The documentation of this feature is there §4 "Verifying exact number of invocations / at least x / never", and the never javadoc is here.
Use the second argument on the Mockito.verify method, as in:
Mockito.verify(dependency, Mockito.times(0)).someMethod()
First of all: you should always import mockito static, this way the code will be much more readable (and intuitive):
import static org.mockito.Mockito.*;
There are actually many ways to achieve this, however it's (arguably) cleaner to use the
verify(yourMock, times(0)).someMethod();
method all over your tests, when on other Tests you use it to assert a certain amount of executions like this:
verify(yourMock, times(5)).someMethod();
Alternatives are:
verify(yourMock, never()).someMethod();
Alternatively - when you really want to make sure a certain mocked Object is actually NOT called at all - you can use:
verifyZeroInteractions(yourMock)
Please Note:
verifyZeroInteractions(Object... mocks) is Deprecated.
Since Version 3.0.1. The now recommended method is:
verifyNoInteractions(yourMock)
As a more general pattern to follow, I tend to use an #After block in the test:
#After
public void after() {
verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}
Then the test is free to verify only what should be called.
Also, I found that I often forgot to check for "no interactions", only to later discover that things were being called that shouldn't have been.
So I find this pattern useful for catching all unexpected calls that haven't specifically been verified.
Both the verifyNoMoreInteractions() and verifyZeroInteractions() method internally have the same implementation as:
public static transient void verifyNoMoreInteractions(Object mocks[])
{
MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}
public static transient void verifyZeroInteractions(Object mocks[])
{
MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}
so we can use any one of them on mock object or array of mock objects to check that no methods have been called using mock objects.
Just as a suggestion, if you want to be more aligned at syntax level with Behavior-driven development style there is BDDMockito:
You could use:
then(dependency).should(never()).someMethod();
As an equivalent replacement of:
verify(dependency, never()).someMethod();
This is the test:
import static junit.framework.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest( {ClassUnderTesting.class} )
public class ClassUnderTestingTest {
#Test
public void shouldInitializeMocks() throws Exception {
CollaboratorToBeMocked mockedCollaborator = mock(CollaboratorToBeMocked.class);
suppress(constructor(CollaboratorToBeMocked.class, InjectedIntoCollaborator.class));
whenNew(CollaboratorToBeMocked.class)
.withArguments(InjectedAsTypeIntoCollaborator.class)
.thenReturn(mockedCollaborator);
new ClassUnderTesting().methodUnderTesting();
assertTrue(true);
}
}
These are the classes :
public class ClassUnderTesting {
public void methodUnderTesting() {
new CollaboratorToBeMocked(InjectedAsTypeIntoCollaborator.class);
}
}
public class CollaboratorToBeMocked {
public CollaboratorToBeMocked(Class<InjectedAsTypeIntoCollaborator> clazz) {
}
public CollaboratorToBeMocked(InjectedIntoCollaborator someCollaborator) {
}
public CollaboratorToBeMocked() {
}
}
public class InjectedAsTypeIntoCollaborator {
}
public class InjectedIntoCollaborator {
}
This is the error :
org.powermock.reflect.exceptions.TooManyConstructorsFoundException: Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're refering to.
Matching constructors in class CollaboratorToBeMocked were:
CollaboratorToBeMocked( InjectedIntoCollaborator.class )
CollaboratorToBeMocked( java.lang.Class.class )
Here comes the question: how can I make PowerMock figure out what constructor to look for?
The problematic line is the suppress. That is where the error comes from.
Perhaps it is too late for your question. I met it today and found the solution at the following url. Basically, you need to specify your argument type like.
whenNew(MimeMessage.class).**withParameterTypes(MyParameterType.class)**.withArguments(isA(MyParameter.class)).thenReturn(mimeMessageMock);
http://groups.google.com/group/powermock/msg/347f6ef1fb34d946?pli=1
Hope it can help you. :)
I didn't know of PowerMock until you wrote your question, but did some reading and found this in their documentation. Still I am not really sure if that helps you:
If the super class have several
constructors it's possible to tell
PowerMock to only suppress a specific
one. Let's say you have a class called
ClassWithSeveralConstructors that has
one constructor that takes a String
and another constructor that takes an
int as an argument and you only want
to suppress the String constructor.
You can do this using the
suppress(constructor(ClassWithSeveralConstructors.class, String.class));
method.
found at http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior
Isn't it the thing you wanted?
EDIT: Now I see, you've already tried suppressing. But are you sure you got the suppress call right? Isn't the first argument of constructor() supposed to be the class you would like to surpress the constructor in?
If using PowerMock for EasyMock you can do PowerMock.expectNew(CollaboratorToBeMocked.class, new Class[]{InjectedIntoCollaborator.class}, ...) where the Class[] is the parameter types of the constructor you're expecting to be called. This will resolve the ambiguity between the constructors.