mvc mockbean español spring mockito autowired value-initialization

mockbean - ¿Cómo me burlo de un campo AutoValue @Value en Spring con Mockito?



spring mvc español (4)

Estoy usando Spring 3.1.4.RELEASE y Mockito 1.9.5. En mi clase de primavera tengo:

@Value("#{myProps[''default.url'']}") private String defaultUrl; @Value("#{myProps[''default.password'']}") private String defaultrPassword; // ...

De mi prueba JUnit, que actualmente tengo configurado así:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:test-context.xml" }) public class MyTest {

Me gustaría burlar un valor para mi campo "defaultUrl". Tenga en cuenta que no quiero simular valores para los otros campos. Me gustaría mantenerlos tal como están, solo el campo "defaultUrl". También tenga en cuenta que no tengo métodos explícitos "setter" (por ejemplo, setDefaultUrl ) en mi clase y no quiero crear ninguno solo con el objetivo de probar.

Dado esto, ¿cómo puedo simular un valor para ese campo?


Ahora era la tercera vez que buscaba en Google esta publicación SO, ya que siempre olvido cómo simular un campo @Value. Aunque la respuesta aceptada es correcta, siempre necesito algo de tiempo para hacer que la llamada a "setField" sea correcta, así que al menos yo mismo pego un fragmento de ejemplo aquí:

Clase de producción:

@Value("#{myProps[‘some.default.url'']}") private String defaultUrl;

Clase de prueba:

import org.springframework.test.util.ReflectionTestUtils; ReflectionTestUtils.setField(myClassUnderTest, "defaultUrl", "http://foo"); // Note: Don''t use MyClassUnderTest.CLASS, use the class itself // Note: Don''t use the referenced string "#{myProps[‘some.default.url'']}", // but simply the FIELDs name ("defaultUrl")


Me gustaría sugerir una solución relacionada, que es pasar los campos @Value -annotated como parámetros al constructor, en lugar de usar la clase ReflectionTestUtils .

En lugar de esto:

public class Foo { @Value("${foo}") private String foo; }

y

public class FooTest { @InjectMocks private Foo foo; @Before public void setUp() { ReflectionTestUtils.setField(Foo.class, "foo", "foo"); } @Test public void testFoo() { // stuff } }

Hacer esto:

public class Foo { private String foo; public Foo(@Value("${foo}") String foo) { this.foo = foo; } }

y

public class FooTest { private Foo foo; @Before public void setUp() { foo = new Foo("foo"); } @Test public void testFoo() { // stuff } }

Beneficios de este enfoque: 1) podemos instanciar la clase Foo sin un contenedor de dependencia (es solo un constructor), y 2) no estamos combinando nuestra prueba con nuestros detalles de implementación (la reflexión nos vincula con el nombre del campo usando una cadena, que podría causar un problema si cambiamos el nombre del campo).


Puede utilizar la magia de Spring''s ReflectionTestUtils.setField para evitar hacer modificaciones a su código.

Consulte this tutorial para obtener más información, aunque probablemente no lo necesite ya que el método es muy fácil de usar.

ACTUALIZAR

Desde la introducción de Spring 4.2.RC1 ahora es posible establecer un campo estático sin tener que proporcionar una instancia de la clase. Vea this parte de la documentación y this compromiso.


También puede burlarse de la configuración de su propiedad en su clase de prueba

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:test-context.xml" }) public class MyTest { @Configuration public static class MockConfig{ @Bean public Properties myProps(){ Properties properties = new Properties(); properties.setProperty("default.url", "myUrl"); properties.setProperty("property.value2", "value2"); return properties; } } @Value("#{myProps[''default.url'']}") private String defaultUrl; @Test public void testValue(){ Assert.assertEquals("myUrl", defaultUrl); } }