with test run example context spring dependency-injection junit mocking transactional

spring - test - ¿Cómo inyecté los simulacros en una clase de primavera marcada como "@Transactional"?



spring boot test (2)

No estoy seguro de la biblioteca burlona que está usando, pero hay una integración útil entre Spring y Mockito llamada torpemente " Springockito " que puede hacer que las inserciones tácticas de los simuladores en un gran contexto de primavera sean bastante fáciles.

La idea es cambiar el contexto de la aplicación de prueba para asignar ese bean a un simulacro, en lugar de intentar conectar el simulacro a su bean padre en el tiempo de ejecución.

Entonces realmente terminas con:

text-context.xml

<beans xmlns="http://www.springframework.org/schema/beans" ... xmlns:mockito="http://www.mockito.org/spring/mockito" xsi:schemaLocation="... http://www.mockito.org/spring/mockito https://bitbucket.org/kubek2k/springockito/raw/tip/springockito/src/main/resources/spring/mockito.xsd"> <mockito:mock id="m_orderDao" class="my.package.OrderDao"/> <!--... other config ...--> </beans>

Luego, puede autoconfigurar el simulacro en su prueba si necesita interactuar con él, de la misma manera que lo está haciendo para su servicio tal como está ahora.

Si no está utilizando Mockito, puede seguir utilizando el método anterior, pero en su lugar use el método de su biblioteca burlona para crear simulaciones como la fábrica para el frijol.

Estoy usando SPring 3.1.1.RELEASE y JUnit 4.8.1. En mi clase de prueba, quiero burlarme de un campo privado y descubrí la belleza de "ReflectionTestUtils" ...

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:test-context.xml" }) public class OrderServiceTest extends AbstractTransactionalJUnit4SpringContextTests … @Autowired private OrderService m_orderSvc; @Test public void testGetPDOrders() throws QuickBaseException, Exception { … ReflectionTestUtils.setField(m_orderSvc, "m_orderDao", mockOrderDao);

A continuación se muestra la clase y el campo que estoy tratando de burlar ...

@Service("orderService") @Transactional public class OrderServiceImpl implements OrderService { … @Autowired private OrderDAO m_orderDao;

Decepcionante, me sale el siguiente error. He leído que esto se debe a que mi clase está marcada como "@Transactional", pero no puedo encontrar una solución adecuada y me parece una pérdida escribir los métodos setter únicamente para dar cabida a JUnit. ¿Alguien tiene otra sugerencia sobre cómo puedo inyectar mi objeto simulado en un campo privado?

java.lang.IllegalArgumentException: Could not find field [m_orderDao] on target [org.mainco.subco.myclient.service.OrderServiceImpl@282f0e07] at org.springframework.util.Assert.notNull(Assert.java:112) at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:107) at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:84) at org.mainco.subco.myclient.service.OrderServiceTest.testGetPDOrders(OrderServiceTest.java:130) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


A partir de 2014, la solución más fácil es usar la anotación @InjectMocks que es parte de Mockito. Esto funciona con cualquier clase, incluidas las marcadas con @Transactional.

Aquí hay un ejemplo :

public class TestTestController { @Mock private TestService testService; @InjectMocks private TestController testController; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test public void testMocks() throws Exception { String mockedReturnValue = "this is a mocked reply"; when(testService.getMessage()).thenReturn(mockedReturnValue); assertEquals(mockedReturnValue, testController.callTestService()); } }

y las clases relacionadas

public class TestController { @Autowired private TestService testService; public String callTestService() { return testService.getMessage(); } } public class TestService { public static final String THIS_IS_A_TEST = "this is a getMessage"; public String getMessage() { return THIS_IS_A_TEST; } }