Un problema obvio con el uso de afirmar

Las pruebas unitarias son una parte importante de cualquier proyecto lo suficientemente grande. Quiero compartir con ustedes una peque帽a historia de detectives relacionada con su ca铆da en masa no obvia.

Comienza con el hecho de que, como resultado de un cierto compromiso inofensivo, alrededor de 150 pruebas cayeron en el proyecto, mientras que el conjunto de pruebas de ca铆da no fue estable. Las pruebas no estaban interconectadas, las pruebas se realizaron secuencialmente. La base de datos h2 en memoria se utiliza como fuente de datos para las pruebas. La ca铆da de la gran mayor铆a de estas 150 pruebas estuvo acompa帽ada por un error en el registro: "No se puede obtener una conexi贸n, error de agrupaci贸n Tiempo de espera en espera de objeto inactivo". Debe decirse que el tama帽o del grupo de conexiones al realizar pruebas en el proyecto es 1.

Una peque帽a digresi贸n l铆rica: en el c贸digo del proyecto, la transacci贸n se desconecta del flujo peri贸dicamente, luego el c贸digo se ejecuta en una transacci贸n separada y, finalmente, la transacci贸n se vincula. Para tales casos, se ha escrito una clase auxiliar, cuyo uso se parece a esto:

TransactionRunner.run(dbDataManager(), new MethodTransaction() { @Override public ExecutionResult runInTransaction() throws Exception { // ,       return result; } ); 

Como resultado del an谩lisis, se revel贸 que el error comienza a aparecer despu茅s de una prueba fallida que contiene una llamada de c贸digo en una transacci贸n:

 TransactionRunner.run(dbDataManager(), new MethodTransaction() { @Override public ExecutionResult runInTransaction() throws Exception { // ...   // assert   assert( 1, result.getSomeNotEqualOneIntValue() ); return result; } ); 

Eche un vistazo dentro de la clase TransactionRunner, una llamada al m茅todo conduce al siguiente c贸digo:

 protected ExecutionResult run() throws CommonException { Transaction outerTr = getThreadTransaction(); bindThreadTransaction(null); try { beginTransaction(); try { setResult(transactionCode.runInTransaction()); } catch (Exception e) { dbDataManager().rollbackTransaction(); if (transaction.onException(this, e)) throw e; } dbDataManager().commitTransaction(); return getResult(); } catch (Exception e) { throw ExceptionUtil.createCommonException(e); } finally { bindThreadTransaction(outerTr); } } 

Entonces, 驴cu谩l es el problema aqu铆? Y el problema es que el AssertionError que surge como resultado de la ejecuci贸n del c贸digo de prueba no se hereda de Exception, lo que significa que la transacci贸n anidada no se revierte ni se confirma. Dado que el tama帽o de la agrupaci贸n de conexiones es igual a uno, obtenemos el mismo error "No se puede obtener una conexi贸n, error de agrupaci贸n Se agot贸 el tiempo de espera del objeto inactivo" al intentar obtener el objeto de conexi贸n mediante pruebas posteriores.

Moraleja: es necesario colocar las afirmaciones en las pruebas con precauci贸n, y en el caso de fallas no obvias y, en particular, masivas, una de las soluciones es verificar si el manejo de excepciones tiene en cuenta los objetos que no se heredan de Exception.

El caso me pareci贸 digno de arreglo, tal vez esta experiencia sea 煤til para alguien.

Source: https://habr.com/ru/post/es420509/


All Articles