java - tutorial - Inyectando una propiedad String con @InjectMocks
spring test (2)
No puedes hacer esto con Mockito, pero Apache Commons en realidad tiene una manera de hacerlo usando una de sus utilidades integradas. Puedes poner esto en una función en JUnit que se ejecuta después de que Mockito inyecte el resto de los simulacros pero antes de que se ejecuten los casos de prueba, como esto:
@InjectMocks
MyClass myClass;
@Before
public void before() throws Exception {
FieldUtils.writeField(myClass, "fieldName", fieldValue, true);
}
Tengo un Spring MVC @Controller
con este constructor:
@Autowired
public AbcController(XyzService xyzService, @Value("${my.property}") String myProperty) {/*...*/}
Quiero escribir una prueba de unidad independiente para este controlador:
@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {
@Mock
private XyzService mockXyzService;
private String myProperty = "my property value";
@InjectMocks
private AbcController controllerUnderTest;
/* tests */
}
¿Hay alguna forma de que @InjectMocks
inyecte mi propiedad String? Sé que no puedo burlarme de una Cuerda ya que es inmutable, pero ¿puedo inyectar una Cuerda normal aquí?
@InjectMocks
inyecta un nulo por defecto en este caso. @Mock
comprensiblemente lanza una excepción si la pongo en myProperty
. ¿Hay alguna otra anotación que haya omitido que simplemente signifique "inyectar este objeto exacto en lugar de una burla"?
No puedes hacer esto con Mockito, porque, como mencionaste, una String
es final
y no puede ser burlada.
Hay una anotación de @Spy
que funciona en objetos reales , pero tiene las mismas limitaciones que @Mock
, por lo que no puede espiar una String
.
No hay anotación para decirle a Mockito que solo inyecte ese valor sin burlarse o espiar. Sin embargo, sería una buena característica. Tal vez lo sugiera en el repositorio de Mockito Github .
Tendrá que crear una instancia manual de su controlador si no desea cambiar su código.
La única forma de tener una prueba basada en anotación pura es refactorizar el controlador. Puede usar un objeto personalizado que solo contiene esa propiedad, o tal vez una clase de configuración con múltiples propiedades.
@Component
public class MyProperty {
@Value("${my.property}")
private String myProperty;
...
}
Esto se puede inyectar en el controlador.
@Autowired
public AbcController(XyzService xyzService, MyProperty myProperty) {
...
}
Puedes burlarte e inyectar esto entonces.
@RunWith(MockitoJUnitRunner.class)
public class AbcControllerTest {
@Mock
private XyzService mockXyzService;
@Mock
private MyProperty myProperty;
@InjectMocks
private AbcController controllerUnderTest;
@Before
public void setUp(){
when(myProperty.get()).thenReturn("my property value");
}
/* tests */
}
Esto no es muy sencillo, pero al menos podrá realizar una prueba basada en anotaciones puras con un poco de stubbing.