Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set value to mocked object but get null

I have a simple class Foo to be mocked:

public class Foo {
   private String name;
   public Foo() {
   }
   public Foo(String name) {
     this.name = name;
   }

   public void setName(String name) {
     this.name = name;
   }
   public String getName() {
     return name;
   }
}

In my unit test code, I mock it by using Mockito.

Foo mockedFoo = Mockito.mock(Foo.class);
mockedFoo.setName("test");
// name is null
String name = mockedFoo.getName();

I set name in mocked object, but when I call getter to get the name it returns null.

Is it a Mockito specific issue or is it an convention that mocked object can't set value? Why is that? What is happening underneath with mocked object?

like image 939
Leem.fin Avatar asked Dec 10 '15 14:12

Leem.fin


People also ask

Why is mock returning null object?

If a method return type is a custom class, a mock returns null because there is no empty value for a custom class. RETURN_MOCKS will try to return mocks if possible instead of null . Since final class cannot be mocked, null is still returned in that case.

How do you set a value to a mocked object?

To solve your problem of knowing whether the setName() method was called in your code with the specified value use the Mockito verify method. For example: verify(mockedFoo, times(1)). setName("test");

How do you initialize a mocked object?

For the mocks initialization, using the runner or the MockitoAnnotations. initMocks are strictly equivalent solutions. From the javadoc of the MockitoJUnitRunner : JUnit 4.5 runner initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.

Does Mockito any match null?

Since Mockito any(Class) and anyInt family matchers perform a type check, thus they won't match null arguments.


2 Answers

Well yes - the actual code of Foo doesn't matter, because you're mocking it... and Mockito doesn't know there's meant to be a relationship between setName and getName. It doesn't assume that it should store the argument to setName and return it when getName is called... it could do that, but it doesn't as far as I'm aware. The mock provided by Mockito just allows you to specify what happens when methods are called on it, and check what was called later on. Instead of calling setName, you could mock a call to getName() and specify what it should return...

... or you could just use Foo directly instead of mocking it. Don't think you have to mock everything in your tests. Just mock (or fake) things that are awkward when you're using the real class, e.g. because it uses the file system or network.

like image 69
Jon Skeet Avatar answered Sep 22 '22 17:09

Jon Skeet


By default mockito has no behavior, on any methods in the mocked object.

You should do something like this:

Foo mockedFoo = Mockito.mock(Foo.class);
when(mockedFoo.getName()).thenReturn("someName");
String name = mockedFoo.getName();

edit: as mentioned by Jon Skeet, you should not need to mock things that can just be tested in a normal fashion.

like image 31
Martin Hansen Avatar answered Sep 22 '22 17:09

Martin Hansen