Prefacio
Este artículo presenta cómo usar SpringBoot+Junit+Mockito para pruebas unitarias, y seleccionar una clase que coincida con las transacciones para realizar pruebas unitarias.
Comprender los requisitos antes de las pruebas unitarias
Para escribir una buena prueba única, primero debe comprender los requisitos. Solo sabiendo qué hacer puedes saber cómo probar. Pero este artículo habla principalmente sobre el uso de Mockito, y no hay necesidad de prestar atención a las necesidades específicas. Por lo tanto, esta sección omite la descripción de requisitos específicos.
Aislar dependencias externas
Caso1. Cómo controlar el valor de retorno del objeto de dependencia anotado por @Autowired o @Resource Annotation en la clase probada
Tomar la coincidencia (MatchingOrder BuyOrder, MatchingOrder SellOrder) del método en Test MatchingServiceImpl.java como ejemplo
Class probada MatchingServiceImpl
Public Class MageServiceImpl implementa MatchingService {private static final logger log = loggerFactory.getLogger (MatchingServiceImpl.class); @AUtowired privado quoteservice cotiservice; ... Public MatchingResult Matching (MatchingOrder BuyOrder, MatchingOrder SellOrder) {int curtivePrice = Quoteservice.getCurrentPricyProduct (buyerLorder.getProductCode ()); MatchingResult Result = new MatchingResult (); if (sellOrder! = null && buyerDER! = null && sellorder.getPrice () <= buyerDer.getPrice ()) {...}}Quoteservice.getCurrentPriceByProduct (buyerDer.getProductCode ()); Para acceder a Redis para obtener la cotización actual, necesitamos burlarse del servicio de cotizaciones de dependencia externa para controlar el valor de retorno del método GetCurrentPricyProduct. Puedes hacerlo usando Mockito, de la siguiente manera:
Prueba de la clase de prueba MatchingServiceImplTest
Public Class MatchingServiceImplTest extiende los objetos MockitObasedTest { / *** marcados por @mock se inyectarán automáticamente en el objeto marcado por @injectMocks* / @mock privado Quoteservice Quoteservice; /** * <pre> * Los objetos a probar, marcados con @InjectMocks, esos objetos marcados por @mock se inyectarán automáticamente en él. * Otro punto notable es que el MatchingServiceImpl es directamente nuevo (está bien si no es nuevo después de Mockito 1.9), en lugar de inyectarse a través del contenedor de resorte. Porque aquí no necesito obtener otras dependencias del contenedor de primavera *, y no necesito base de datos, redis, Zookeeper, MQ, y nada depende de ello, así que directamente nuevo *</ pre> */ @@InjectMocks MatchingingeServiceImpl MatchingService = New MatchingServiceImpl (); @Test public void testMatching_SuccesswhencurrentPriceBetbewrUyPRiceandSellPrice () {MatchingOrder BuyOrder = new MatchingOrder (); buyerDer.setPrice (1000); buyerLor.setCount (23); MatchingOrder SellOrder = new MatchingOrder (); SellOrder.setPrice (800); SellOrder.setCount (20); // Método Stubbing (método Stubbing) // Cuando (x) .thenreturn (y): devuelve el valor especificado cuando el método especificado se llama Mockito.When (Quoteservice.getCurrentPricyByProduct (Mockito.AnyString ())). MatchingResult Result = MatchingService.matching (BuyerLor, SellOrder); org.junit.assert.assertEquals (true, resultado.issuccess ()); // afirmar si el emparejamiento es exitoso org.junit.assert.assertequals (20, result.getTradeCount ()); // afirmar la cantidad de transacción org.junit.assertequals (900, result.getTradeprice ())); // afirmar si la última cita cumple con las expectativas}Caso2. Cuando se prueba la función A, ¿cómo controlar el valor de retorno de la función B en la clase bajo prueba?
Por ejemplo, hay una función StartBuyProcess en MatchingServiceImpl, que llama a otras funciones en la clase, como GetTOpSellorder y Matching. ¿Cómo controlar los valores de retorno de estas dos funciones?
El problema que se resolverá aquí es en realidad cómo ejecutar realmente el método medido (como StartBuyProcess) de una clase de clase "simulada parcial" de clase, mientras que otros métodos (como GetTOpSellorder) están apilados (no entran realmente y ejecutan).
Class probada MatchingServiceImpl
inicio void protegido (MatchingOrder BuyerRorder, boolean WaitFormatching) {while (true) {// El mejor precio de la contraparte MatchingOrder topsellorder = getToPSellorder (buyerLorder.getProductCode ()); MatchingResult MatchingResult = Matching (BuyOrder, TopSellorder); if (matchingResult.issuccess ()) {domatchingsuccess (buyerDer, topSellorder, MatchingResult, MatchingType.buy); if (buyerDer.getCount () <= 0) {break; }} else {if (waitFormatching) {// Agregar para que coincida con la cola que se coincida con addTomatchingBuy (buyerLOR); } else {// Revoca el pedido sendCancLemsg (buyerDer); } romper; }}}}El uso de Mockito.spy () puede lograr "simulacro parcial"
Test Class MatchingServiceImpltest.TestStartBuyProcess_incaseOfMatchingSuccess
/** * * Pruebe si el procesamiento del método StartBuyProcess después de un emparejamiento exitoso cumple con las expectativas, es decir, pruebe el comportamiento después de ingresar la siguiente rama de juicio * {@link MatchingServiceImpl#startBuyProcess (MatchingOrder, boolean)} * * <pRE> * if (ResultResult.issUdResUlsUltResUltResUltResUlTResUlsUltResLeL MatchingType.buy); * * if (buyerDORD.getCount () <= 0) { * break; *} *} * </ pre> * */ @Test public void testStartBuyProcess_incaseOfMatchingSuccess () {MatchingOrder BuyOrder = new MatchingOrder (); buyerDer.setPrice (700); buyerLor.setCount (23); // use mockito.spy () para almohar parcialmente el servicio MatchingService MatchingService = Mockito.spy (MatchingService); MatchingResult FirstMatchingResult = new MatchingResult (); FirstMatchingResult.SetSuccess (verdadero); FirstMatchingResult.SetTradeCount (20); MatchingResult SecondMatchingResult = new MatchingResult (); SecondMatchingResult.SetSuccess (falso); // doreturn (x) .When (obj) .method () Después de apilar los métodos, después de apilar los métodos, el programa devolverá el valor especificado como se esperaba al ejecutar estos métodos. Los métodos que no están apilados se ejecutarán se ejecutarán en tiempo real. // Dos doreturns significa que FirstMatchingResult se devuelve cuando MatchingService.Matching se llama primero, y SecondMatchingResult se devuelve cuando se llama la segunda llamada // porque hay un bucle de tiempo en StartBuyProcess, el método de coincidencia puede ejecutarse múltiples mockito.doreturn (FirstMatchingResult). Doreturn (Doreturn (Doreturn (doreta). .matching (Mockito.ally (MatchingOrder.Class), Mockito.Aly (MatchingOrder.Class)); MatchingOrder SellOrder = new MatchingOrder (); SellOrder.setPrice (600); SellOrder.setCount (20); // acumulando el método getTopSellorder Mockito.doreturn (SellOrder) .When (MatchingService) .GetTOpSellorder (Mockito.AnyString ()); // acumulando el método externo que depende de Jedis Mockito.When (JedIsclient.incrby (Mockito.anystring (), Mockito.anylong ())). Luego, Return (0l); // startBuyProcess es la función en prueba. Si no se acumula, MatchingService.StartBuyProcess (BuyOrder, True); // La afirmación de suma de verificación posterior es probar el comportamiento del método de domatchingsuccess, que también es el propósito de esta prueba .// Verificar se puede usar para verificar cuántas veces se ha ejecutado un determinado método de clase. Aquí es para verificar si JedIsclient.zremfirst ha sido ejecutado una vez Mockito.verify (JEdIsClient, Mockito.Times (1)). Zremfirst (Mockito.AnyString ()); org.junit.assert.assertecals (3, buyerDer.getCount ()); org.junit.assert.assertecals (0, sellOrder.getCount ()); } Se ha demostrado el uso de espía. Hablemos sobre la "granularidad" de las pruebas unitarias de TestStartBuyProcess_incaseOfMatchingSuccess.
El propósito de TestStartBuyProcess_IncaseOfMatchingSuccess es probar domatchingsuccess. Hemos trabajado muy duro para terminar los preparativos anteriores antes de poder probar el domingo.
Una mejor práctica debe ser comenzar un nuevo método de prueba para probar el dominio de domats por separado, y el enfoque también se concentra. Después de que se sobrescribe Domatchingsuccess, StartBuyProcess en realidad puede cubrir su propia rama de juicio. La cobertura aún se alcanza y el código de prueba es más fácil de mantener. TestStartBuyProcess_incaseOfMatchingSuccess se ve fácilmente afectado por los cambios debido a demasiadas responsabilidades consideradas. Cambio de cosas pequeñas pueden afectar su función normal.
Introducción del marco de prueba Dependencias Maven
<Spendency> <MoupRId> Junit </Groupid> <AtifactId> Junit </artifactid> <verserse> 4.11 </verse> <cope> test </cope> </pendency> <pendency> <grupoD> org.mockito </proupId> <artifactid> mockito-all </artifactid> <lansione> 1.10.19 </Versión>> Versión> <cope> test </scope> </pepertency> <pendency> <grupid> org.springframework </groupid> <artifactid> test test </artifactid> <versión> 4.2.5.release </versión> <apope> test </pope> </dependency>
Contexto Construcción de Springboot+Junit+Mockito
Teta mackitobed
@RunWith (SpringJunit4ClassRunner.class) @SpringApplicationConfiguration (classes = testApplication.class) public abstract Class MockitObasedTest {@bebore public void setup () lanza excepción {// inicializar todos los objetos simulados anotados por las anotaciones de mockito en las anotaciones de las casas de prueba mockitoannotations. }} // Otras clases de prueba heredan MockitObasedTest Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.