Empecé a usar ng-mocks hace un par de semanas porque pensé que estaba diseñado con este caso en mente, pero por mi vida no sé cómo implementarlo.
En resumen, ¿se puede cambiar el valor de los proveedores simulados en descripciones/pruebas anidadas después de haber definido MockBuilder/MockRender?
En mi aplicación, a menudo tengo componentes que se basan en Servicios que brindan diferentes datos según el contexto. En los casos en que esto es estático, es lo suficientemente simple como para probarlo. Usaré ActivatedRoute aquí como ejemplo, ya que es uno que me está dando problemas:
const mockActivatedRoute = { snapshot: { params: { id: 1 } }; describe('MyComponent', () => { MockInstance.scope('all'); beforeEach(() => { return MockBuilder(MyComponent, MyModule) .provide({ provide: ActivatedRoute, useValue: mockActivatedRoute }) }); beforeEach(() => { fixture = MockRender(MyComponent); component = fixture.point.componentInstance; }); // Imagine the component has a routeId provided by the ActivatedRoute it('should have an id of 1', () => { expect(component.routeId).toEqual(1); }); });Hasta aquí todo bien.
Pero después de esa prueba quiero ejecutar otra suite que modifique el servicio; digamos que la id ahora será 2. Asumí que este era el rol de MockInstance : poder cambiar los servicios proporcionados y demás sobre la marcha para una prueba determinada.
Entonces, para continuar con mi ejemplo, ahora agregaré una describe anidada dentro de la primera después de mi primera prueba:
describe('MyComponent', () => { ... describe('when it inits with a different id', () => { MockInstance.scope(); beforeEach(MockInstance(mockActivatedRoute, () => { snapshot: { params: { id: 2 } } })); it('should have an id of 2', () => { expect(component.routeId).toEqual(2); }); }); }); Esta prueba fallará, ya que el nuevo valor simulado nunca se implementó y el routeId de ruta permaneció sin cambios.
Me doy cuenta de que este es un mal ejemplo. He reescrito estas pruebas de muchas maneras diferentes usando MockInstance.remember o tratando de iniciar la instancia del servicio en sí, pero no he tenido ningún éxito. Por lo que puedo decir, no parece que MockBuilder y MockInstance estén destinados a usarse juntos y no hay ejemplos de esto en el sitio ng-mocks. Parece que la única forma de crear pruebas para casos como este es crear describes separadas, cada una con su propio MockBuilder y MockRender.
¿O mi mejor opción es simplemente hacer público routeId y manipularlo directamente?
MockBuilder se puede usar con MockInstance . Es importante tener en cuenta que MockInstance funciona con servicios que aún no se han inicializado. En otras palabras, tiene efecto antes que MockRender o TestBed.createComponent .
Una vez que se haya llamado a cualquiera de ellos, debe obtener instancias a través TestBed.inject y simularlas directamente, por ejemplo, con ngMocks.stub y ngMocks.stubMember .
const service = TestBed.inject(Service); let value: any; ngMocks.stubMember(service, 'name', v => (value = v), 'set'); // value === undefined service.name = 'fake'; // value === 'fake' En su segunda prueba, desea cambiar ActivatedRoute , por lo tanto, debe usarla en lugar de mockActivatedRoute , también, debido a que reutiliza TestBed entre pruebas, debe confiar en TestBed.inject en lugar de MockInstance :
beforeEach(() => { const activatedRoute = TestBed.inject(ActivatedRoute); ngMocks.stub(activatedRoute, { snapshot: { params: { id: 2, }, }, }); });