{"id":22273505,"url":"https://github.com/dfleta/mocking-examples","last_synced_at":"2025-03-25T16:41:46.292Z","repository":{"id":236117885,"uuid":"791950637","full_name":"dfleta/mocking-examples","owner":"dfleta","description":"Uso de mockito con TDD","archived":false,"fork":false,"pushed_at":"2024-04-26T22:31:17.000Z","size":222,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-30T14:44:50.722Z","etag":null,"topics":["junit4","mock","mock-test","mockito","tdd","tdd-java","tdd-kata"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dfleta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-25T17:25:38.000Z","updated_at":"2024-04-26T22:31:20.000Z","dependencies_parsed_at":"2024-04-25T18:50:06.694Z","dependency_job_id":null,"html_url":"https://github.com/dfleta/mocking-examples","commit_stats":null,"previous_names":["dfleta/mockito-ejemplo"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fmocking-examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fmocking-examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fmocking-examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dfleta%2Fmocking-examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dfleta","download_url":"https://codeload.github.com/dfleta/mocking-examples/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245501804,"owners_count":20625855,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["junit4","mock","mock-test","mockito","tdd","tdd-java","tdd-kata"],"created_at":"2024-12-03T13:12:56.181Z","updated_at":"2025-03-25T16:41:46.254Z","avatar_url":"https://github.com/dfleta.png","language":"Java","readme":"Ejemplo uso Mockito\n===================\n\nSupongamos que nos encontramos en la construcción mediante TDD de la aplicación especificada en el ejercicio [Cotxox](https://github.com/dfleta/cotxox \"cotxox\").\n\nLa clase `Carrera` depende de la lógica que por SRP corresponde a las clases que implementan las interfaces `Conductora`, `PoolConductora` y `Tarifa`.\n\nSi las historias de usuario más valiosas suponen la implementación de la clase `Carrera` llegaremos el momento en el que necesitaremos la información proporcionada por los componentes de los que depende. Si la lógica o algoritmia y el diseño de estas clases supone cierta dificultad que no puede ser resuelta de manera ágil, podemos aplicar los principios SOLID para mantener las interfaces públicas de dichos componentes adheridas a dichos principios y \"mockear\" o crear métodos _stub_ que sustituyan dichas funcionalidades. \n\nUtilizamos [mockito](https://site.mockito.org/) como _framework_ en Junit para construir el comportamiento descrito.\n\nMockito, además, nos ofrece la posibilidad de realizar cierta reflexión sobre el comportamiento de las clases que \"mockea\", \"espiar\" en las tripas de los objetos mockeados, para comprobar que el comportamiento es como suponemos, al igual que hacía [Slimer](slimer.webp \"Slimer ghost busters\")\n en cazafantasmas.\n\n\n```java\n@Test\npublic void asignarConductor(){\n\t// Utilizamos las interfaces para crear los mocks\n\t// de Conductora y PoolConductoras\n\t// pues en ellas disponemos de los\n\t// métodos abstractos sin implementación.\n\tConductora mockConductor = mock(Conductora.class);\n\twhen(mockConductor.getNombre()).thenReturn(\"Samantha\");\n\n\tcarrera.setConductor(null);\n\tassertNull(carrera.getConductor());\n\n\tPoolConductoras mockPool = mock(PoolConductoras.class);\n\twhen(mockPool.asignarConductor()).thenReturn(mockConductor);\n\n\tcarrera.asignarConductor(mockPool);\n\t// verificamos que asignarConductor() de PoolConductora\n    // ha sido invocado a través de carrera.asignarConductor()\n\tverify(mockPool).asignarConductor();\n\n\tassert(carrera.getConductor()!=null);\n\tassertEquals(\"Samantha\", carrera.getConductor().getNombre());\n}\n```\n\n## Diagrama de clases UML\n\n![Diagrama de clases UML](./diagrama_clases_UML.png \"Diagrama de clases UML\")\n\n## Referencia de Mockito\n\nAquí un [tutorial](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html \"tutorial mockito\") con ejemplos básicos de uso. Conviene que lo leas para usar los mocks de manera eficiente:\n\nhttps://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html\n\nNo está de más leerse esta [RefCard](https://dzone.com/refcardz/mockito \"refcard mockito\"):\n\nhttps://dzone.com/refcardz/mockito\n\n## Microservicios con moc(kit)os\n\nTestear aplicaciones en el Mundo Real TM es un poco más complicado y, si a la dificultad añadida por la arquitectura cliente-servidor, le sumamos la de una arquitectura basada en microservicios, lejos de las placenteras aplicaciones monolíticas, entonces es necesario disponer de un conocimiento más profundo de la API del _framework_ de testig y mock.\n\nEn mi proyeto [grpc-tourism-receptive](https://github.com/dfleta/grpc-tourism-receptive) encontrarás a mockito y Slimer en acción en una aplicación basada en el framework gRPC de Google para la construcción de aplicaciones basadas en microservicios, implementando el patrón GoF _observer_ para implementar la lógica de un receptivo turístico al estilo mallorquín ;)\n\nhttps://github.com/dfleta/grpc-tourism-receptive\n\nAquí los casos test: [test grpc](https://github.com/dfleta/grpc-tourism-receptive/tree/master/src/test/java/org/elsmancs/grpc)\n\nEn los test de los componentes \"clientes\" de los servidores se concentra el uso de mockito, para simular que disponemos de servidores de pago, crisal y UFOs que proveen de los objetos que necesitamos para completar el desarrollo de los componentes cliente indendientemente de su estado de desarrollo y funcionamiento:\n\n* [PaymentClientTest](https://github.com/dfleta/grpc-tourism-receptive/blob/master/src/test/java/org/elsmancs/grpc/payment/PaymentClientTest.java)\n* [CrystalClientTest](https://github.com/dfleta/grpc-tourism-receptive/blob/master/src/test/java/org/elsmancs/grpc/crystal/CrystalClientTest.java)\n* [UfosParkClientTest](https://github.com/dfleta/grpc-tourism-receptive/blob/master/src/test/java/org/elsmancs/grpc/ufos/UfosParkClientTest.java)\n\n```java\n@Test\npublic void UfoOf_test() {\n\n    // Mensaje CreditCard al servicio\n    CreditCard card = CreditCard.newBuilder()\n                                    .setOwner(\"Rick\")\n                                    .setNumber(\"111111111111\")\n                                    .build();\n\n    AtomicReference\u003cCreditCard\u003e cardDelivered = new AtomicReference\u003cCreditCard\u003e();\n\n    // Mock de la respuesta /mensaje Processed del servicio\n    Ufo responseUfo = Ufo.newBuilder()\n                            .setId(\"unox\")\n                            .setCardNumbe(\"111111111111\")\n                            .setFee(500)\n                            .build();\n\n    // Fake service\n    UfosParkImplBase assignImpl = new UfosParkImplBase() {\n        @Override\n        public void ufoOf(CreditCard request, StreamObserver\u003corg.elsmancs.grpc.Ufo\u003e response) {\n            // para chequear que la construccion del Ufo en el client se realiza OK\n            cardDelivered.set(request);\n            // return the Ufo\n            response.onNext(responseUfo);\n            // Specify that we’ve finished dealing with the RPC.\n            response.onCompleted();\n        }\n    };\n\n    serviceRegistry.addService(assignImpl);\n\n    String ufoID = client.UfoOf(\"Rick\", \"111111111111\");\n\n    assertEquals(card, cardDelivered.get());\n    assertEquals(responseUfo.getId(), ufoID);\n}    \n```\n\n## Frontend testing \u0026 mocks\n\nEn mi proyecto ejemplo sobre el patrón _proxy_ (+ _singleton_), patrón _flyweight_, herencia por prototipos en JS, prototipos delegados, extensión dinámica de objetos, _constructor functions_ [proxy pattern mr meeseeks](https://github.com/dfleta/proxy-pattern-mrMeeseks-js) encontrarás ejemplos de uso de mocking en front, utilizando la librería [Jest](https://jestjs.io/es-ES/ \"jest\") para JavaScript /EmacScript.\n\nEs conveniente leer el manual de la librería sobre [funciones mock](https://jestjs.io/es-ES/docs/mock-functions)\n\nEn estos casos test se hace uso de las funcionalidades de Jest para mockear componentes JavaScript:\n\n* [box.test](https://github.com/dfleta/proxy-pattern-mrMeeseks-js/blob/master/src/box/test/box.test.js)\n\n* [mrmeeseeks.test](https://github.com/dfleta/proxy-pattern-mrMeeseks-js/blob/master/src/mrmeeseeks/test/mrmeeseeks.test.js)\n\n```js\ntest('fullfillRequest ejecuta this.accion()', () =\u003e {\n\n        // MOCK FUNCTIONS con IMPLEMENTATIONS\n\n        /**\n         * La funcion accion que necesita fulfillRequest\n         * ha de ser creada previamente por makeRequest()\n         * e inyectada en el objeto meeseeks.\n         * No podemos depender de la implementacion de makeRequest()\n         * para pasar este test =\u003e mockear la funcion accion() que\n         * inyecta makeRequest() e inyectarla a mano en el objeto meeseeks \n         */\n\n        const accionMock = jest\n                            .fn()\n                            .mockImplementation( () =\u003e \"open\" + \" \" + \"Jerry's head\")\n                            .mockName('accionMock') // mensajes especificos en test errors outputs\n\n        // inyecto en el objeto la funcion mock\n        meeseeks.accion = accionMock;\n        expect(meeseeks).toHaveProperty('accion'); // primera invocacion de la funcion accionMock\n        \n        // el objeto meeseeks invoca a la funcion mock == segunda invocacion de la función mock\n        expect(meeseeks.fulfillRequest()).toEqual(expect.stringMatching(\"open\" + \" \" + \"Jerry's head\" + \" All done!!\"))\n\n        // accionMock ha debido ser llamada desde fulfillRequest()\n        expect(accionMock).toHaveBeenCalled();\n        // La funcion ha sido llamada exactamente dos veces: toHaveProperty + fullfillRequest\n        expect(accionMock.mock.calls.length).toBe(2);\n        // El valor devuelto en la segunda llamada a la funcion ha sido \"open Jerry's head\"\n        expect(accionMock.mock.results[1].value).toBe(\"open Jerry's head\");\n        // La funcion ha sido llamada con un cierto contexto `this`: el objeto `meeseeks`\n        expect(accionMock.mock.contexts[0]).toBe(meeseeks);\n        // Ek primer argumento de la ultima llamada a la funcion ha sido 'undefined', accion()\n        expect(accionMock.mock.lastCall[0]).toBe(undefined);\n    });\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfleta%2Fmocking-examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdfleta%2Fmocking-examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdfleta%2Fmocking-examples/lists"}