java - example - Mockito-NullpointerException cuando se apaga Método
mockito verify spy (10)
Así que empecé a escribir pruebas para nuestro proyecto Java-Spring.
Lo que uso es JUnit y Mockito. Se dice que cuando uso la opción when () ... thenReturn () puedo simular servicios, sin simularlos. Entonces lo que quiero hacer es establecer:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
Pero no importa qué cláusula de cuándo lo haga, siempre obtengo una NullpointerException, lo que, por supuesto, tiene sentido, porque la entrada es nula.
También cuando intento burlarme de otro método desde un objeto:
when(object.method()).thenReturn(true)
Allí también obtengo un Nullpointer, porque el método necesita una variable, que no está establecida.
Pero quiero usar when () .. thenReturn () para evitar crear esta variable y así sucesivamente. Solo quiero asegurarme de que si alguna clase llama a este método, no importa qué, simplemente devuelva true o la lista anterior.
¿Es un malentendido básicamente de mi lado, o hay algo más mal?
Código:
public class classIWantToTest implements classIWantToTestFacade{
@Autowired
private SomeService myService;
@Override
public Optional<OutputData> getInformations(final InputData inputData) {
final Optional<OutputData> data = myService.getListWithData(inputData);
if (data.isPresent()) {
final List<ItemData> allData = data.get().getItemDatas();
//do something with the data and allData
return data;
}
return Optional.absent();
}
}
Y aquí está mi clase de prueba:
public class Test {
private InputData inputdata;
private ClassUnderTest classUnderTest;
final List<ItemData> allData = new ArrayList<ItemData>();
@Mock
private DeliveryItemData item1;
@Mock
private DeliveryItemData item2;
@Mock
private SomeService myService;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
myService = mock(myService.class);
classUnderTest.setService(myService);
item1 = mock(DeliveryItemData.class);
item2 = mock(DeliveryItemData.class);
}
@Test
public void test_sort() {
createData();
when(myService.getListWithData(inputdata).get().getItemDatas());
when(item1.hasSomething()).thenReturn(true);
when(item2.hasSomething()).thenReturn(false);
}
public void createData() {
item1.setSomeValue("val");
item2.setSomeOtherValue("test");
item2.setSomeValue("val");
item2.setSomeOtherValue("value");
allData.add(item1);
allData.add(item2);
}
El valor de retorno predeterminado de los métodos que aún no ha tocado es false
para los métodos booleanos, una colección vacía o un mapa para los métodos que devuelven colecciones o mapas y, de lo contrario, null
.
Esto también se aplica a las llamadas de método dentro de when(...)
. En su ejemplo, when(myService.getListWithData(inputData).get())
provocará una myService.getListWithData(inputData)
NullPointerException porque myService.getListWithData(inputData)
es null
, no se ha eliminado antes.
Una opción es crear simulacros para todos los valores de retorno intermedios y eliminarlos antes de usarlos. Por ejemplo:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
O alternativamente, puede especificar una respuesta predeterminada diferente al crear un simulacro, para hacer que los métodos devuelvan un nuevo simulacro en lugar de nulo: RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
Debe leer el Javadoc de Mockito.RETURNS_DEEP_STUBS que explica esto con más detalle y también tiene algunas advertencias sobre su uso.
Espero que esto ayude. Solo tenga en cuenta que su código de ejemplo parece tener más problemas, como faltar aseverar o verificar declaraciones y llamar a los configuradores en simulacros (lo que no tiene ningún efecto).
En mi caso, me perdí agregar primero
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
Así que esto puede ser útil para alguien que ve tal error.
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
Frente al mismo problema, la solución que me funcionó:
En lugar de burlarse de la interfaz de servicio, usé @InjectMocks para simular la implementación del servicio:
@InjectMocks
private exampleServiceImpl exampleServiceMock;
en lugar de :
@Mock
private exampleService exampleServiceMock;
La answer Ed Webb ayudó en mi caso. Y en su lugar, también puedes probar agregar
@Rule public Mocks mocks = new Mocks(this);
Si tu @RunWith(JUnit4.class)
.
Para los futuros lectores, otra causa de NPE cuando se usan simulacros es olvidar iniciar los simulacros de esta manera:
@Mock
SomeMock someMock;
@InjectMocks
SomeService someService;
@Before
public void setup(){
MockitoAnnotations.initMocks(this); //without this you will get NPE
}
@Test
public void someTest(){
Mockito.when(someMock.someMethod()).thenReturn("some result");
// ...
}
Para mí, la razón por la que recibía NPE es que estaba usando Mockito.any()
cuando se burlaban de los primitivos. Descubrí que al usar la variante correcta de mockito se eliminan los errores.
Por ejemplo, para simular una función que toma un parámetro primitivo long
, en lugar de usar any()
, debería ser más específico y reemplazarlo con any(Long.class)
o Mockito.anyLong()
.
Espero que ayude a alguien.
Aclamaciones
Tuve el mismo problema y mi problema era simplemente que no había anotado la clase correctamente usando @RunWith. En tu ejemplo, asegúrate de que tienes:
@RunWith(MockitoJUnitRunner.class)
public class Test {
...
Una vez que hice eso, las NullPointerExceptions desaparecieron.
Tuve este problema y mi problema era que estaba llamando a mi método con any () en lugar de anyInt (). Así que tuve:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
y tuve que cambiarlo a:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
No tengo idea de por qué eso produjo una NullPointerException. Tal vez esto ayude a la próxima pobre alma.
Caso de la esquina:
Si está utilizando Scala e intenta crear un emparejador any
en una clase de valor , obtendrá un NPE inútil.
Entonces, dada la case class ValueClass(value: Int) extends AnyVal
, lo que quiere hacer es ValueClass(anyInt)
lugar de any[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
...
val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
...
}
Esta otra pregunta de SO es más específicamente sobre eso, pero la perdería cuando no sepa que el problema es con las clases de valor.
@RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class
@PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{
@Mock
Context mockContext;
@Mock
SharedPreferences mSharedPreferences;
@Mock
SharedPreferences.Editor mSharedPreferenceEdtor;
@Before
public void setUp() throws Exception
{
// mockContext = Mockito.mock(Context.class);
// mSharedPreferences = Mockito.mock(SharedPreferences.class);
// mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}
@Test
public void deletePreferencesTest() throws Exception {
}
}
No se requieren todos los códigos comentados anteriormente { mockContext = Mockito.mock(Context.class);
}, si usa @Mock Annotation to Context mockContext;
@Mock
Context mockContext;
Pero funcionará si usa @RunWith (MockitoJUnitRunner.class) solamente. Según Mockito, puede crear un objeto simulado utilizando @Mock o Mockito.mock (Context.class); ,
Obtuve la NullpointerException debido al uso de @RunWith (PowerMockRunner.class), en lugar de eso, cambié a @RunWith (MockitoJUnitRunner.class) funciona bien