DEV Community

TDD in Angular - Dependency Injection and Mocking

Bearded JavaScripter on May 28, 2020

In our last article here, we went through the basic structure of an Angular Unit Test and went on to test services. In this article, I want to show...
Collapse
 
stealthmusic profile image
Jan Wedel • Edited

I am struggling with TDD in Angular ever since I have started and I was really hoping to find some answers here.

In the backend (Java), TDD just comes naturally.

But in the UI, there is more than services and component logic. There is layouting and a mixture of those. So, I often ask myself where do I start to write tests?

I am just developing a complex master/detail component and I was fiddling with choosing the right display material components, wiring data bindings etc until I wrote the first test.

This actually made me feel really uncomfortable, actually kind of dirty.

I would love to start with Cypress tests, then probably layouting, then Unit tests and then implement logic but just doesn’t work. I tried.

I am wondering how you Or others do it?

One last bit: Using TestBed integration tests slows down the test speed significantly (from 20md each test to 3-4seconds) for a complex component. That is inacceptable. So we refactored all jasmine tests to be pure unit tests of components and to all DOM testing in Cypress.

Collapse
 
qarunqb profile image
Bearded JavaScripter

Bear in mind, I have a lot more articles coming up that definitely touch and explain more on the topics in this thread. It's just a matter of getting them out but I'm really glad to see that all these points come up so I know what to focus on in my articles and what to prioritize.

Really grateful for all your comments :D ❤️

Collapse
 
stealthmusic profile image
Jan Wedel

Looking forward to that!

Collapse
 
qarunqb profile image
Bearded JavaScripter

As per the Angular Style Guide, we try our best to keep the application logic in services and anything to do with UI in components. So you can test the majority of your application logic through testing services and, instead of accessing the DOM from jasmine/jest, you can leave that to cypress.

Collapse
 
stealthmusic profile image
Jan Wedel

Yeah, mostly yes. But you’d still have mappings from backend to component models, validation logic, event emitters and stuff you want to test.

But my question was more like: Can you build a whole angular application test-driven? Does it even make sense?

It just feels bad not to TDD everything to me but it doesn’t work when ever I try.

Thread Thread
 
qarunqb profile image
Bearded JavaScripter

When you say mappings from backend to component models, validation logic, event emitters, what do you mean?

Do you mean testing http requests, validation of data submitted to backend routes and testing Observables, events received from the backend?

Angular allows you to test those things using an HttpInterceptor, so you can create a mock backend. In terms of unit testing, you'd want to isolate your front end from your back end. You can connect them when it's time for an e2e tests, most of my articles cover Unit Testing for now, e2e is definitely something I have to get into more.

If your back end is already built, you can streamline your mock backend to mimic how data is supposed to be returned, throw in a few errors just to see how your front end handles it.

I could be misunderstanding what you're referring to though.

Collapse
 
layzee profile image
Lars Gyrup Brink Nielsen • Edited

The first call to ComponentFixture#detectChanges runs ngOnChanges and ngOnInit.

Collapse
 
qarunqb profile image
Bearded JavaScripter

Thank you for the correction! Will edit this now

Collapse
 
bodote profile image
bodote

I think MockInventoryService is not necessary here. You can make a spy without it.
Your tests would do just fine, if you use the real service, but using the spyOn()'s .and.returnValue() method, or any other of spyOn()'s methods, to make the spy do what you need for your test.
That would save you a lot of lines of code.

Collapse
 
bravemaster619 profile image
bravemaster619

Angular TDD is really annoying when you have to inject every dependency to TestBed for each component.

Collapse
 
qarunqb profile image
Bearded JavaScripter

Yep it can get annoying at times. At that point, there's usually a compromise to be made between the number of dependencies for a component and what the conponent can do in terms of features.

There are articles that say to keep the dependencies per component less that 3, but sometimes it's inevitable