Pruebas automatizadas de enlace completo

Antecedentes
Desde la arquitectura SOA hasta la ahora popular arquitectura de microservicios, el sistema se ha vuelto cada vez más pequeño y la complejidad de la arquitectura general también ha aumentado linealmente. Las dificultades técnicas y las soluciones bajo la arquitectura de microservicios de las que siempre hemos hablado se han vuelto cada vez más maduro (incluida la coherencia de datos típica. Hay muchas soluciones al problema de coherencia causado por las llamadas al sistema, o al problema de coherencia causado por la replicación entre nodos y salas de computadoras), pero hay un vínculo que obviamente hemos ignorado.

Según la tendencia actual de la arquitectura de microservicios, los microservicios son básicamente relativamente completos en términos de operación, mantenimiento e implementación automatizada. Desde mi experiencia personal, los grandes cambios provocados por el desarrollo y las pruebas de nivel superior de la arquitectura de microservicios todavía se están reflejando y aprendiendo.

En el nivel de desarrollo, los microservicios se discuten más sobre el marco, la gobernanza, el rendimiento, etc. Sin embargo, desde la perspectiva de la ingeniería de software completa, carecemos seriamente de conocimientos de análisis y diseño, que también es una tecnología de la que generalmente carecen nuestros ingenieros actuales.

A menudo nos damos cuenta de lo difícil que es reconstruir algo, porque hubo una grave falta de análisis y diseño exhaustivos durante la construcción del edificio en las primeras etapas, lo que eventualmente llevó a que el edificio se volviera rígido y finalmente aterrador. Poco a poco se convierte en un monstruo. (Por ejemplo, los desarrolladores rara vez escriben unitTest y siempre ignoramos el valor de la ingeniería de software detrás de las pruebas unitarias).

El eslabón olvidado en la ingeniería de software: DEVTESTOPS ¿
Hemos descubierto un fenómeno? En todo el proceso de software, las pruebas se pasan por alto fácilmente. Cualquier modelo de ingeniería de software tiene un vínculo de control de calidad, pero este vínculo parece ser muy delgado y débil. En la actualidad, la mayoría de nuestros ingenieros y arquitectos han subestimado seriamente el poder y el valor de este vínculo y todavía están atrapados en pruebas funcionales manuales sin conocimientos técnicos. contenido En la impresión de baja eficiencia.

Esto es principalmente para probar todo el sistema técnico del personaje y sus débiles capacidades de ingeniería. Parte de esto es un problema ambiental objetivo y algunos de sus propios problemas. No se ha permitido salir y aprender más sobre toda la tecnología de ingeniería y comprender más. sobre la tecnología de desarrollo, la arquitectura física de la producción, que ayudará a la prueba a amplificar su propio sonido.

Otra razón principal por la que la innovación general en el diseño del proceso de prueba es débil en China es que los ingenieros de desarrollo generalmente no tienen una base de ingeniería completa. En los países extranjeros desarrollados en TI, como Japón y Estados Unidos, los límites entre un ingeniero de desarrollo calificado y un ingeniero de pruebas son borrosos. Ellos desarrollan sus propios productos y los prueban ellos mismos. Esto requiere un cambio en el modo de pensar y la necesidad de tener ambos. habilidades al mismo tiempo, pero este es el todo El proceso completo de la ingeniería de software.

¿Alguna vez nos hemos preguntado por qué ahora todo el mundo habla de DevOps en lugar de DevTestOps y por qué se saltan el enlace de prueba? ¿El sistema desarrollado no necesita capacidad de prueba si necesita tener buena operabilidad y mantenibilidad? Necesidades de desarrollo Tener operación y mantenimiento capacidades. La operación y el mantenimiento requieren capacidades de desarrollo. ¿Por qué se ignora el enlace de prueba?

Nuestro desprecio por el vínculo de control de calidad y nuestra falta de énfasis en el papel de las pruebas en realidad tienen efectos secundarios muy graves.

Probando problemas de complejidad y eficiencia bajo la arquitectura de microservicios.
La granularidad de la división de microservicios es mucho más fina que la de SOA. Medido a partir de la implementación automática de imágenes en contenedores, es muy conveniente después de dividirse en tamaños más pequeños, pero causará problemas para el Todo el desarrollo y el proceso de prueba agregan una gran complejidad y problemas de eficiencia.

En la era SOA, el principio basado en contratos también se aplica a los microservicios: después de definir el contrato para los requisitos entre departamentos, puede desarrollarlo y lanzarlo primero. Pero el mayor problema en esto es el problema de la depuración continua parcial y la regresión automática del sistema actual. Si un nuevo sistema se conecta, es necesario realizar pruebas de estrés de rendimiento y cómo resolver estas dependencias externas.

Tal vez digamos, ¿no debería la parte que confía estar lista primero y luego podemos probarla y publicarla de inmediato? Si el negocio y la estructura son razonables, el mayor problema en este escenario es que nuestros proyectos son fácilmente controlados por partes dependientes, lo que causará muchos problemas. Por ejemplo, el personal de I + D necesita cambiar para hacer otras cosas y la sucursal siempre está colgando. Puede haber pasado un mes o más antes de que alguien de repente se acerque a usted y le diga que se puede conectar. Una vez que este método se convierte en un proceso de desarrollo habitual, es fácil producir errores en línea.

Otra situación que también es razonable es que el proveedor de la plataforma necesita llamar a la interfaz del lado comercial, que incluye la interfaz de devolución de llamada generalmente llamada, la interfaz de marketing en el enlace de transacción, la interfaz de enrutamiento de entrega, etc.

Aquí nos gustaría compartir con usted nuestro proyecto en curso de motor de reglas de marketing en la nube.

marketing-cloud proporciona algunos servicios de marketing, incluidas compras grupales, cupones, promociones, etc., pero nuestro lado comercial necesita tener sus propias actividades de marketing personalizadas. Necesitamos abstraer las actividades de marketing del lado comercial en el motor de reglas de marketing-cloud. Devolver información y, al mismo tiempo, conectar actividades de marketing personalizadas con transacciones públicas y enlaces de liquidación para formar un flujo comercial completo.

Este es un diagrama de arquitectura lógica de marketing en la nube. Relacionado con nuestro tema está el motor de reglas de marketing, que es lo que aquí llamamos un escenario empresarial razonable.

Durante todo el proceso de pedido directo, el motor de reglas de marketing no solo debe proporcionar actividades de marketing compartidas dentro de la nube de marketing, sino también unir varios métodos de marketing de centros de marketing externos. Habrá múltiples centros de marketing externos. Actualmente, hay dos principales unos.

Dado que este artículo no trata sobre cómo diseñar una plataforma de marketing, no ampliaré el tema aquí. Su principal objetivo es atraer nuevas ideas. Las empresas tipo plataforma tendrán varios escenarios comerciales que dependerán de sistemas externos. La siguiente parte del artículo ampliará la práctica del motor de reglas de marketing en la nube para abrir enlaces de prueba.

Durante la fase de desarrollo, unitTest se burla de las dependencias externas.
En la fase de desarrollo, escribiremos regularmente pruebas unitarias para probar nuestra lógica. Al escribir unitTest, necesitamos simular las dependencias circundantes. Los objetos del simulacro se dividen en dos tipos, uno no hay objetos stub con lógica Assert, y también hay un objeto de simulación simulado que necesita admitir Assert.

Pero no es necesario distinguirlos claramente. La diferencia entre los dos no es demasiado obvia y es posible que sea necesario distinguirla dentro de los estándares de codificación.

Lo que nos preocupa es cómo resolver el problema de dependencia entre objetos. Varios marcos simulados en realidad proporcionan muchas herramientas muy útiles. Podemos burlarnos fácilmente de las dependencias circundantes.

given(marketingService.mixMarketingActivity(anyObject())).willReturn(stubResponse);
RuleCalculateResponse response = this.ruleCalculatorBiz.ruleCalculate(request);

Aquí nos burlamos del método marketingService.mixMarketingActivity().

El mundo Java proporciona muchos marcos de burla útiles. Uno de los marcos más populares y útiles, Mockito, puede burlarse fácilmente de las dependencias de la capa de servicio. Por supuesto, además de Mockito, hay muchos marcos de burla excelentes.

Estos marcos son similares. El mayor problema al escribir unitTest es cómo reconstruir la lógica para que sea más fácil de probar, es decir, si el código tiene buena capacidad de prueba, si se han eliminado la mayoría de los métodos privados y si hay acusaciones sobre privados. métodos No capturamos el concepto de negocio.

Simulacro de dependencias externas en la etapa de depuración continua
. Después de haber completado todo el desarrollo, las pruebas unitarias completas garantizan que nuestra lógica interna esté libre de problemas (por supuesto, no discutiremos aquí si el diseño del caso unitTest es perfecto).

Ahora necesitamos conectar y ajustar el desarrollo del sistema periférico, que todavía pertenece a otros sistemas de soporte como esta plataforma. Por ejemplo, la relación entre nuestro sistema de motor de reglas de marketing en la nube y el sistema de realización de pedidos. Durante el desarrollo, escribimos unitTest y completamos con éxito el trabajo de verificación de la solución de desarrollo, pero ahora nos enfrentamos a continuos problemas de depuración.

El sistema necesita ser administrado oficialmente, pero carecemos de dependencia de centros de marketing externos, ¿qué debemos hacer? De hecho, también necesitamos burlarnos de las dependencias externas durante la fase de depuración continua, pero esta tecnología y método simulados no son compatibles con el marco unitTest, sino que requieren que diseñemos la arquitectura de desarrollo de todo nuestro servicio nosotros mismos.

En primer lugar, es necesario poder identificar que esta solicitud requiere burlarse, luego se necesita algún tipo de parámetro simulado para proporcionar capacidades de identificación.

Echemos un vistazo a un intento preliminar del motor de reglas de marketing de marketing en la nube en esta área.

public interface CCMarketingCentralFacade {
    CallResponse callMarketingCentral(CallRequest request);
}
public interface ClassMarketingCentralFacade {
    CallResponse callMarketingCentral(CallRequest request);
}

El motor de reglas de marketing utiliza la API del cliente RestEasy como marco de llamadas restantes. Estas dos fachadas son fachadas iniciadas por la plataforma de marketing hacia los centros de marketing de CCTalk y Hujiang Online School Hujiang.

(Para restaurar nuestra práctica de ingeniería tanto como sea posible y necesitamos eliminar cierta información confidencial, en todos los ejemplos de código de todo el artículo, eliminé algunos códigos que no afectan la lectura y son irrelevantes para este artículo, y también hice algunos pseudocodificación y omisiones, lo que hace que el código sea más ágil y fácil de leer).

Bajo la lógica normal, decidiremos a qué interfaz del centro de marketing de la empresa llamar en función de la clave de ruta de marketing. Sin embargo, cuando estábamos desarrollando este proyecto, el lado comercial no tenía una dirección existente a la que conectarnos, por lo que hicimos un simulacro. fachada nosotros mismos para resolver el problema del ajuste continuo.

public class CCMarketingCentralFacadeMocker implements CCMarketingCentralFacade {
 
    @Override
    public CallResponse callMarketingCentral(CallRequest request) {
 
        CallResponse response = ...
        MarketingResultDto marketingResultDto = ...
        marketingResultDto.setTotalDiscount(new BigDecimal("90.19"));
        marketingResultDto.setUseTotalDiscount(true);
 
        response.getData().setMarketingResult(marketingResultDto);
 
        return response;
    }
}
public class ClassMarketingCentralFacadeMocker implements ClassMarketingCentralFacade {
 
    @Override
    public CallResponse callMarketingCentral(CallRequest request) {
        CallResponse response = ...
 
        MarketingResultDto marketingResultDto = ...
        marketingResultDto.setUseCoupon(true);
        marketingResultDto.setTotalDiscount(null);
        marketingResultDto.setUseTotalDiscount(false);
 
        List<MarketingProductDiscountDto> discountDtos = ...
 
        request.getMarketingProductTagsParameter().getMarketingTags().forEach(item -> {
 
            MarketingProductDiscountDto discountDto = ...
            discountDto.setProductId(item.getProductID());
            ...
            discountDtos.add(discountDto);
        });
...
        return response;
    }
}

Definimos dos  clases simuladas  , las cuales son datos de prueba, para resolver el problema en la etapa de depuración continua, es decir, el problema de dependencia del   entorno DEV .

Después de tener  la fachada simulada  , debe  solicitar  definir  los parámetros simulados  .

public abstract class BaseRequest implements Serializable {
    public MockParameter mockParameter;
}
public class MockParameter {
 
    /**
     * mock cc 营销调用接口
     */
    public Boolean mockCCMarketingInterface;
 
    /**
     * mock class 营销调用接口
     */
    public Boolean mockClassMarketingInterface;
 
    /**
     * 是否自动化测试 mock
     */
    public Boolean useAutoTestMock;
 
    /**
     * 测试mock参数
     */
    public String testMockParam;
 
}

Ignoremos los diseños universales por el momento. Este es solo un intento iterativo que hicimos mientras nos apresurábamos al proyecto. Consideraremos reconstruir el marco de extracción después de haber recorrido todo el proceso.

Con los parámetros de entrada, podemos inyectar dinámicamente una fachada simulada según el criterio de los parámetros.

Requisitos simulados en la fase de prueba automatizada
Seguimos avanzando y, después de pasar la fase de depuración continua, ingresamos a la fase de prueba. Ahora, básicamente, la mayoría de las empresas de Internet realizan pruebas automatizadas y hay muy pocas pruebas manuales, especialmente para los sistemas back-end. .

Entonces, uno de los problemas que enfrentamos en la etapa de prueba automática es que necesitamos una dirección de prueba automática pública. Esta dirección de prueba no se modifica. La dirección del bean fachada de nuestro simulacro bajo pruebas automatizadas es esta dirección. El valor generado por esta dirección debe ser capaz de corresponder a En el contexto de cada ejecución de script de automatización.

Tenemos muchos sistemas de microservicios para formar una plataforma, y ​​cada servicio tiene una interfaz de terceros dependiente. Resulta que al probar automáticamente estos servicios, es necesario comprender la interfaz, la base de datos, la entrada frontal, etc. sistema, porque al escribir automatización Al realizar secuencias de comandos, es necesario crear datos de prueba sincrónicamente y, finalmente, afirmar.

Esta eficiencia de comunicación y colaboración entre departamentos es muy baja, y los cambios de personal y de sistema afectarán directamente el ciclo de lanzamiento. Definitivamente vale la pena innovar aquí para resolver este grave problema de obstrucción de la eficiencia.

@Value("${marketing.cloud.business.access.url.mock}")
private String mockUrl;
/**
     * 自动化测试 mocker bean
     */
    @Bean("CCMarketingCentralFacadeTestMock")
    public CCMarketingCentralFacade CCMarketingCentralFacadeTestMock() {
        RestClientProxyFactoryBean<CCMarketingCentralFacade> restClientProxyFactoryBean ...
        restClientProxyFactoryBean.setBaseUri(this.mockUrl);
        ...
    }
 
    /**
     * 自动化测试 mocker bean
     */
    @Bean("ClassMarketingCentralFacadeTestMock")
    public ClassMarketingCentralFacade ClassMarketingCentralFacadeTestMock()  {
        RestClientProxyFactoryBean<ClassMarketingCentralFacade> restClientProxyFactoryBean ...
        restClientProxyFactoryBean.setBaseUri(this.mockUrl);
        ...
    }

La URL simulada aquí es la dirección de prueba automática unificada que abstrajimos. Hay un parámetro de tipo booleano useAutoTestMock en el parámetro simulado anterior. Si la solicitud actual para este parámetro es verdadera, inyectaremos dinámicamente el bean simulado de prueba automatizado y todas las llamadas posteriores se realizarán. Vaya al lugar especificado por mockUrl.

Apareció autoTest Mock Gateway
Hasta ahora, nos hemos encontrado con la necesidad de una dirección simulada unificada para pruebas automatizadas para cerrar todos los microservicios en este sentido. El mayor problema ahora es que todos los microservicios dependen de diferentes respuestas externas. Cuando se ejecuta el script automatizado, la respuesta creada previamente debe poder adaptarse al contexto de la prueba actual.

Por ejemplo, en el motor de reglas de marketing, nuestro script automatizado necesita preconstruir el producto actual (por ejemplo, ID de producto: 101010) al crear un pedido, obtener la respuesta de información de actividad e información de deducción proporcionada por el centro de marketing externo, y finalmente vaya a Afirmar Si la cantidad y la información de actividad del pedido se registran correctamente es un contexto de prueba automática.

Hay dos formas de identificar el contexto de prueba automática actual: una es determinar la ID del producto cuando se ejecuta el caso y finalmente obtener la respuesta del simulacro a través de la ID del producto. Otra opción es admitir el paso de parámetros simulados de autoTest al servicio especificado por mockUrl. Puede utilizar este parámetro para identificar el contexto de prueba actual.

Un caso de prueba puede pasar por muchos microservicios, y es posible que todos estos servicios dependientes necesiten preestablecer respuestas simuladas, lo que básicamente se hace de una vez por todas.

Por lo tanto, abstraemos el autoTest Mock Gateway (servicio de puerta de enlace simulada de prueba automatizada). Todavía queda mucho trabajo por respaldar en todo el proceso de prueba automatizado, incluida la autenticación entre servicios, la simulación de claves de autenticación, el cifrado y descifrado, y cifrado y descifrado de claves, casos de prueba automatizados simulados se ejecutan alternativamente en paralelo, etc.

Como ingenieros, todos esperamos utilizar un enfoque sistemático y de ingeniería para resolver problemas generales en lugar de problemas puntuales individuales. Con esta puerta de enlace simulada, podemos hacer muchas cosas y también puede beneficiar a todos los demás departamentos que la necesiten.

Construya la respuesta simulada en un contexto de prueba automática y luego use los parámetros simulados para identificar dinámicamente el servicio fuente específico para enrutamiento, autenticación, cifrado y descifrado y otras operaciones.

MockGateway es un punto de apoyo, y creo que este punto de apoyo puede aprovechar una gran cantidad de espacio de prueba y capacidades de innovación.

Implementación de la versión ligera
A continuación mostraremos nuestro intento preliminar en el motor de reglas de marketing de marketing-cloud.

Arquitectura lógica general

El script de automatización creará el autoTestContext correspondiente al caso actual cada vez que ejecute un caso, que contiene algunos metadatos para indicar cuál de todos los sistemas de microservicios involucrados en este caso necesita usar la puerta de enlace simulada.

Todas las configuraciones en mockGateway corresponden a un autoTestContext, si no existe un autoTestContext significa que es común a todos los casos.

Incorporar parámetros simulados en el contrato de solicitud estándar del marco de servicio.
Si desea abrir todos los canales en toda la arquitectura de microservicios, debe definir parámetros simulados en el contrato de solicitud estándar. Esta es la premisa de todo esto.

El contrato de solicitud de microservicio estándar se utiliza para llamadas entre servicios. La dependencia entre servicios y sistemas externos se puede elegir para usar el encabezado HTTP o la solicitud estándar. Depende de si todo nuestro marco de servicio ha cubierto todas las líneas de producción y algunos problemas del sistema heredado.

public abstract class BaseRequest implements Serializable {
    public MockParameter mockParameter;
}

BaseRequest es la clase base de todas las solicitudes, para garantizar que todas las solicitudes puedan entregarse normalmente.

Utilice AOP + RestEasy HttpClientRequest SPI para implementar inicialmente Mock.
Las dependencias jerárquicas de la arquitectura de desarrollo de todo el sistema son: fachada->biz->servicio. Toda la lógica central básica está en servicio. La solicitud solicitada no puede cruzar el límite hacia el capa de servicio como máximo. Según la especificación, la solicitud dto está atascada en la capa de negocios como máximo, pero en el mundo de Internet, algunas se pueden iterar rápidamente y no es una regla rígida. La reconstrucción oportuna es el método principal para pagar la deuda técnica.

Ya hemos mencionado antes que el marco RPC que utilizamos es el cliente RestEasy + RestEasy, primero veamos la entrada.

@Component
@Path("v1/calculator/")
public class RuleCalculatorFacadeImpl extends BaseFacade implements RuleCalculatorFacade {
    @MockFacade(Setting = MockFacade.SETTING_REQUEST_MOCK_PARAMETER)
    public RuleCalculateResponse ruleCalculate(RuleCalculateRequest request)  {
    ...
    }
}

Miremos nuevamente  el objeto de servicio  .

@Component
public class MarketingServiceImpl extends MarketingBaseService implements MarketingService {
    @MockFacade(Setting = MockFacade.SETTING_FACADE_MOCK_BEAN)
    public MarketingResult onlyExtendMarketingActivity(Marketing..Parameter tagsParameter) {
    ...
    }

Centrémonos en  la  declaración de anotación @MockFacade .

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MockFacade {
 
    String SETTING_REQUEST_MOCK_PARAMETER = "setting_request_mock_parameter";
    String SETTING_FACADE_MOCK_BEAN = "setting_facade_mock_bean";
 
    String Setting();
}

A través de esta anotación, nuestro objetivo principal es colocar   el  parámetro simulado en ThreadLocal  y limpiarlo después de procesar la solicitud. Otra función es  el procesamiento de simulacros de beans  de  la capa de servicio  .

@Aspect
@Component
@Slf4j
public class MockMarketingFacadeInterceptor {
 
    @Before("@annotation(mockFacade)")
    public void beforeMethod(JoinPoint joinPoint, MockFacade mockFacade) {
 
        String settingName = mockFacade.Setting();
 
        if (MockFacade.SETTING_REQUEST_MOCK_PARAMETER.equals(settingName)) {
 
            Object[] args = joinPoint.getArgs();
            if (args == null) return;
 
            List<Object> argList = Arrays.asList(args);
            argList.forEach(item -> {
 
                if (item instanceof BaseRequest) {
                    BaseRequest request = (BaseRequest) item;
 
                    if (request.getMockParameter() != null) {
                        MarketingBaseService.mockParameterThreadLocal.set(request.getMockParameter());
                        log.info("----setting mock parameter:{}", JSON.toJSONString(request.getMockParameter()));
                    }
                }
            });
        } else if (MockFacade.SETTING_FACADE_MOCK_BEAN.equals(settingName)) {
 
            MarketingBaseService marketingBaseService = (MarketingBaseService) joinPoint.getThis();
            marketingBaseService.mockBean();
            log.info("----setting mock bean.");
        }
    }
 
    @After("@annotation(mockFacade)")
    public void afterMethod(JoinPoint joinpoint, MockFacade mockFacade) {
 
        if (MockFacade.SETTING_FACADE_MOCK_BEAN.equals(mockFacade.Setting())) {
 
            MarketingBaseService marketingBaseService = (MarketingBaseService) joinpoint.getThis();
            marketingBaseService.mockRemove();
 
            log.info("----remove mock bean.");
        }
 
        if (MockFacade.SETTING_REQUEST_MOCK_PARAMETER.equals(mockFacade.Setting())) {
 
            MarketingBaseService.mockParameterThreadLocal.remove();
 
            log.info("----remove ThreadLocal. ThreadLocal get {}", MarketingBaseService.mockParameterThreadLocal.get());
        }
    }
}

Estas lógicas se basan completamente en una convención, que es MarketingBaseService, que no es universal, solo se reconstruye y extrae gradualmente y eventualmente se convertirá en un   marco de complemento .

public abstract class MarketingBaseService extends BaseService {
 
    protected ClassMarketingCentralFacade classMarketingCentralFacade;
 
    protected CCMarketingCentralFacade ccMarketingCentralFacade;
 
    public static ThreadLocal<MockParameter> mockParameterThreadLocal = new ThreadLocal<>();
 
    public void mockBean() {
 
        MockParameter mockParameter = mockParameterThreadLocal.get();
 
        if (mockParameter != null && mockParameter.mockClassMarketingInterface) {
            if (mockParameter.useAutoTestingMock) {
                this.setClassMarketingCentralFacade(SpringContextHolder.getBean("ClassMarketingCentralFacadeTestMock", ClassMarketingCentralFacade.class));
            } else {
                this.setClassMarketingCentralFacade(SpringContextHolder.getBean("ClassMarketingCentralFacadeMocker", ClassMarketingCentralFacadeMocker.class));
            }
        } else {
            this.setClassMarketingCentralFacade(SpringContextHolder.getBean("ClassMarketingCentralFacade", ClassMarketingCentralFacade.class));
        }
 
        if (mockParameter != null && mockParameter.mockCCMarketingInterface) {
            if (mockParameter.useAutoTestingMock) {
                this.setCcMarketingCentralFacade(SpringContextHolder.getBean("CCMarketingCentralFacadeTestMock", CCMarketingCentralFacade.class));
            } else {
                this.setCcMarketingCentralFacade(SpringContextHolder.getBean("CCMarketingCentralFacadeMocker", CCMarketingCentralFacadeMocker.class));
            }
        } else {
            this.setCcMarketingCentralFacade(SpringContextHolder.getBean("CCMarketingCentralFacade", CCMarketingCentralFacade.class));
        }
    }
 
    public void mockRemove() {
        mockParameterThreadLocal.remove();
    }
}

Podemos colocar con éxito el parámetro simulado en la solicitud en ThreadLocal e inyectar dinámicamente el simulacroBean correspondiente a través de AOP.

Lo que todavía tenemos que abordar ahora es llamar a mockGateway para colocar la cadena de identificación en autoContext en __mockParameter_ en el encabezado HTTP.

@Component
public class MockHttpHeadSetting implements ClientRequestFilter {
 
    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
 
        MultivaluedMap<String, Object> header = requestContext.getHeaders();
 
        MockParameter mockParameter = MarketingBaseService.mockParameterThreadLocal.get();
 
        if (mockParameter != null && StringUtils.isNotBlank(mockParameter.getTestingMockParam())) {
            header.add("Mock-parameter", mockParameter.getTestingMockParam());
        }
    }
}

Luego   configúrelo en el archivo SPI (javax.ws.rs.ext.Providers)

com.hujiang.marketingcloud.ruleengine.service.MockHttpHeadSetting

Resumen
En toda la práctica de la arquitectura de microservicios, lo que ha faltado en la discusión de la comunidad de ingenieros es la prueba de la arquitectura de microservicio. Lo más parecido a nosotros son las pruebas automatizadas, porque básicamente todos los sistemas requieren pruebas automatizadas.

Pero hay un área a la que no le hemos prestado mucha atención que es la prueba de estrés de enlace completo. Realizar una prueba de estrés de enlace completo real en producción requiere resolver muchos problemas. El más importante es la BD, todas las transacciones generadas. durante la prueba de estrés. Los datos no pueden participar en los procesos financieros y de liquidación, lo que requiere el uso de tablas paralelas. No todos los datos se escribirán en los datos finales de la transacción real. Por supuesto, hay otros lugares que deben resolverse. Una vez que se activa el interruptor de prueba de estrés de enlace completo, todos los lugares que generan datos deben procesarse. Este es un proyecto enorme, pero también será muy interesante.

Este artículo es solo nuestro primer intento en esta área y continuaremos expandiéndonos. Podemos usar la arquitectura práctica actual para expandirnos durante la próxima prueba de estrés de enlace completo de la línea de producción.

Los siguientes son materiales de apoyo para el aprendizaje. Para aquellos que están haciendo [pruebas de software], debería ser el almacén de preparación más completo y completo. Este almacén también me ha acompañado en el viaje más difícil. ¡Espero que también pueda ayudarlos a ustedes!

 

Supongo que te gusta

Origin blog.csdn.net/2301_76643199/article/details/133134138
Recomendado
Clasificación