Testing functions in class which expects string in constructor using Mockito - java

I have the following class and want to write unit test for it. Below is the class for full reference. X is POJO
public class StatusTable {
private P tableData;
private Q tableDefinition;
public StatusTable(final List<X> xList,
final A a,
final B b)
throws URISyntaxException {
setTableDefinition(a, b);
setTableData(xList, b, a);
}
private void setTableDefinition(final A a,
final B b) {
//some code
}
public void setTableData(final List<X> xList,
final B b, final A a)
throws URISyntaxException {
for (X sfm : xList) {
//some code
}
}
}
Being new to unit testing, I have very minimal idea of how to test but here is a thought. Please correct me wherever incorrect.
public class StatusTableTest {
private StatusTable statusTable;
#Mock
private A mockA;
#Mock
private B mockB;
#Mock
private X mockX;
public void setUp() {
stub(mockX.getSomeValue()).toReturn(?); //want to return any string
stub(mockX.getSomeAnotherValue()).toReturn(?); //want to return any integer
//Similarly mock other functions retuning
this.statusTable = new StatusTable(xList, mockA, mockB,);
}
public void setTableDefinitionTest() {
//test the code
}
}
I have a few doubts:
a) Am I doing it correctly? Should the X be mocked?
b) Is there anyString() kind of functionality in Mockito or should I use something else?

a) It is hard to tell without actual code. You can mock individual X values or whole List of X.
b) Your end result is based on expected values, so you should not return anyString(), but some specific String. So you can verify that your code behaves correctly for this particular String. I.e. assert that table contains single cell with "abc" text if passed list with one X returning "abc".

Depending on what you want to mock.
You can mock any call to your class and return any value or spy on an existing class and overload a call with your mocked call.
For instance
mockedX = Mockito.mock(X.class);
Mockito.when(mockedX.someFunction("1")).thenReturn(someAnswer);
or:
X x = new X();
spiedX = Mockito.spy(x);
Mockito.answer(some answer).when(spiedX).someFunction("1");
Remember ... the mocked class will return what you are mocking.
If you create a mock like this:
Mockito.when(mockedX.someFunction(Mockito.anyString())).thenReturn("A");
then on every call someFunction() will return "A".

Related

is there any way in Mockito I set a rule to return a value when a property of a specific object type is called?

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");

how to destroy static objects? - issue when testing a static field

I would like to test this class and don't want to set id public or allow it to set it from outside.
public class A {
private int id;
private static int prevId = 0;
private static nextId(){
prevId++;
}
public A(){
id = nextId()
}
public int getId(){
return id;
}
...
}
if I test it and generate object of A in set up:
A foo;
#Before
public void setUp(){
foo = new A();
}
#Test
public void test1(){
assertEquals(1, foo.getId());
}
#Test
public void test2(){
assertEquals(1, foo.getId());
}
the test fails because setUp is called twice and therefore
the static field id is 2
assert fail not equals
expected 1
actual 2
As said above I don't want to have id with public access modifier,
otherwise I could set it to 0 by my own.
Is there a way to destroy the a static object in
the tear down method ?
#After
public void tearDown(){
//TODO finalize static object A
}
Quite simply - you can't, without providing some means to reset the prevId value. Decreased testability is one of the (many) arguments against mutable global state.
Instead of relying upon mutable global state like this, you can provide a factory class to create your A instances:
class AFactory {
private int nextId;
A createA() {
return new A(nextId++);
}
}
You will need to inject a single instance of AFactory wherever you currently need to create A instances. Now, in your test, you can simply create a new AFactory for each test case, and the nextId value will be start at zero each time.
Alternatively, you could invert control by creating some sort of unique value provider class:
final class UniqueValueProvider {
private int nextId;
int nextId() {
return nextId++;
}
}
and then make this a parameter of the constructor of A:
class A {
final int id;
A(UniqueValueProvider uvp) {
this.id = uvp.nextId();
}
}
which makes it more extensible if you want to arbitrarily subclass A:
class ChildOfA extends A {
ChildOfA(UniqueValueProvider uvp) {
super(uvp);
}
}
Again, in your tests you can simply create a new instance of UniqueValueProvider; you'd need to inject a single instance everywhere that you need to create an A (or one of its subclasses).
As a side note: you can also change the thing that you are testing. Instead of asserting that the ID is 1 each time, you can create two instances, and assert that the IDs are different/1 greater than the other etc:
Foo first = new Foo();
Foo second = new Foo();
assertNotEqual(first.getId(), second.getId());
If it is really just about the test scenario you described, just use reflection to reset value of the static member variable in your #Before method. If you are using Mockito, you can use their Whitebox helper to achieve this in a single line like so:
import org.mockito.internal.util.reflection.Whitebox;
Foo foo = new Foo();
#Before
public void setup() {
Whitebox.setInternalState(foo, "STATIC_MEMBER", 0);
}
#Test
public void staticMemberTest() {
assertEquals(0, foo.next());
assertEquals(1, foo.next());
}
#Test
public void anotherStaticMemberTest() {
assertEquals(0, foo.next());
assertEquals(1, foo.next());
}
private static class Foo {
private static int STATIC_MEMBER = 0;
public int next() {
return STATIC_MEMBER++;
}
}

Testing local scoped object with mockito without refactoring

Say I have the following code:
public class ClassToTest
{
AnotherClass anotherClass;
public void methodToTest( int x, int y )
{
int z = x + y
anotherClass.receiveSomething( z );
}
}
public class AnotherClass
{
public void receiveSomething( int z ) {.. do something.. }
}
I want to make assertion on the value of the variable z. How do I do this without refactoring? Variables x, y, and z could be some other Java class types, and I just used "int" for simplicity.
You can write the following. Of course dependency injection and test method might change depending on your current implementation and/or your test scenarios.
#RunWith(MockitoJUnitRunner.class)
public class ClassToTestTest {
#Mock AnotherClass anotherClass;
#InjectMocks ClassToTest classToTest;
#Test public void ensure_that_value___Z___is_passed_to___AnotherClass() {
classToTest.methodToTest(1, 2);
verify(anotherClass).receiveSomething(eq(3));
}
}
Written with Mockito 1.9.5-rc1 in mind.
Also instead of using the eq matcher you can instead use an ArgumentCaptor, which will capture values or value references (in case of objects). You'll be able to perform additional assertions on the captured value(s). For example using Truth or FEST-Assert.
This could look like :
#RunWith(MockitoJUnitRunner.class)
public class ClassToTestTest {
...
#Captor ArgumentCaptor<List<Z>> listCaptor
#Test public void ensure_that_list_with_value___Z___is_passed_to___AnotherClass() {
// given
// when
...
// then
verify(anotherClass).receiveList(listCaptor.capture());
assertThat(listCaptor.getValue()).contains(Z);
}
}
Cheers,

Mock that a method call was attempted during unit test, but do not actually call it

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.

Using Mockito's ArgumentCaptor class to match a child class

The below code shows my problem. Effectively, I am trying to use Mockito's ArgumentCaptor to verify that a method was called once with a certain concrete class. I would like to use ArgumentCaptor here if possible, but I am beginning to suspect I need to use a custom ArgumentMatcher instead.
The problem is that the line Mockito.verify(mocked).receive(captor.capture()); (Edit: Added this to the code below) fails with a TooManyActualInvocations exception (2 instead of 1). I would like to understand why this is happening - is it poor implementation of Mockito or a limitation caused by type erasure of generics?
public class FooReceiver {
public void receive(Foo foo) {
}
}
public interface Foo {
}
public class A implements Foo {
}
public class B implements Foo {
}
public class TestedClass {
private FooReceiver receiver;
public TestedClass(FooReceiver receiver) {
this.receiver = receiver;
}
public void doStuff() {
receiver.receive(new A());
receiver.receive(new B());
}
}
public class MyTest {
#Test
public void testingStuff() {
// Setup
FooReceiver mocked = Mockito.mock(FooReceiver.class);
TestedClass t = new TestedClass(mocked);
// Method under test
t.doStuff();
// Verify
ArgumentCaptor<B> captor = ArgumentCaptor.forClass(B.class);
Mockito.verify(mocked).receive(captor.capture()); // Fails here
Assert.assertTrue("What happened?", captor.getValue() instanceof B);
}
}
EDIT:
For anyone interested, I ended up doing this:
// Verify
final B[] b = new B[1];
ArgumentMatcher<B> filter = new ArgumentMatcher<B>() {
#Override
public boolean matches(Object argument) {
if(argument instanceof B) {
b[0] = (B) argument;
return true;
}
return false;
}
}
Mockito.verify(mocked).receive(Mockito.argThat(filter));
As far as I can tell this is a limitation / poor implementation.
When looking at org.mockito.internal.matchers.CapturingMatcher there is
public boolean matches(Object argument) {
return true;
}
meaning it matches every argument / class.
This results in org.mockito.internal.matchers.CapturingMatcher#getAllValues returning a List<B> but actually containing one A and one B resulting in a ClassCastException during runtime when trying to get them as B.
List<Object> arguments; // the invocations
// adds a new invocation
public void captureFrom(Object argument) {
// ...
this.arguments.add(argument);
// ...
}
// return the list of arguments, using raw types remove any compiler checks for validity,
// the returned List contains elements that are not of type T
public List<T> getAllValues() {
// ...
return new ArrayList<T>((List) arguments);
// ...
}
This should be solvable by changing org.mockito.ArgumentCaptor in a way that it passes its Class<? extends T> clazz into the CapturingMatcher and therefore passing the type information along properly, enabling a proper matches implementation and removing the need for the cast / raw type usage.
You can also use Mockito.isA to verify that the argument is of a specific class:
verify(mock).init(isA(ExpectedClass.class));
Mockito JavaDoc
The method will be called twice so you need to do this:
Mockito.verify(mocked, times(2)).receive(captor.capture());

Categories

Resources