Loading Posts...

Faking Dependencies in Angular Applications

Faking Dependencies in Angular Applications
Experimental props. Photo by rawpixel.com on Pexels.

Using the power of Angular’s dependency injection system, we can fake specific use cases. This is useful for automated tests, but in this article, we’ll look at a way to use it for manual testing.

In “Testing and Faking Angular Dependencies”, we created an Internet Explorer 11 deprecation banner component and added test suites. We didn’t test it in an actual Internet Explorer 11 browser yet.

To make life easier for ourselves, we’ll create a browser faker component that’s only enabled in development mode thanks to a custom structural directive. For fun, we’ll add text pipes to use common string operations in our component templates.

Simulating A Browser Environment

While we should always test in our actual browser targets — in this case Internet Explorer 11, we might want the convenience of easily simulating other browser environments during development without leaving our browser of choice.

Currently, the deprecation banner component has a direct dependency on the isInternetExplorer11Token. Replacing a dependency with another value dynamically would require us to intercept the injector chain with a conditionally inserted ancestor component or directive.

Dynamically Replacing a Dependency using a Class-based Service

The user agent token factory is only evaluated once per module injector and if it’s not replaced in an element injector provided by an ancestor component or directive, we have to use another technique to fake the dependency. We’ll replace the dependency injection token dependency with a class-based service dependency.

First, we extract the Internet Explorer 11 detection from the dependency injection token to our newly created InternetExplorerService class. The Internet Explorer 11 detection token now delegates to the service when evaluating its value based on the user agent.

At this point, the application should still be working. Unfortunately, we broke the test suite, so we restructure it to use the Internet Explorer service.

As already mentioned, we won’t dynamically replace the user agent token declaratively in a template using an element injector. Instead, we’ll change the state imperatively.

Creating an Observable State

Instead of the user agent token, we’ll make the Internet Explorer service depend on an observable which it’ll get from a separate browser service.

We store the current user agent state in a BehaviorSubject which is exposed in the observable userAgent$ property of BrowserService. The whole application should depend on this observable when it needs the user agent.

Initially, the behaviour subject is hydrated with the real user agent string from the user agent token. This value is also stored for later use, since we allow to change the browser state through two commands.

We expose the fakeUserAgent method which sets the user agent state to a fake user agent string. Additionally, we allow a dependee to call the stopFakingUserAgent method which resets the user agent state to the real user agent string.

To keep a tidy ship, we even remember to complete the behaviour subject if the service is ever destroyed.

The Internet Explorer service now exposes an observable property called isInternetExplorer11$ which is evaluated whenever the observable user agent property of the browser service emits a value.

All we need now is to have the deprecation banner component depend on the observable Internet Explorer 11 detection property instead of the regular property which we replaced.

In the deprecation banner component, we replace the Boolean isDismissed property with a BehaviorSubject which is initially cleared (set to false). We now have an observable isBannerVisible$ property which is a combination of the observable state from isDismissed and InternetExplorerService#isInternetExplorer11$. The UI behaviour logic is similar to before, except it’s now expressed as part of the observable pipeline.

Instead of assigning a Boolean value to a property, the onDismiss event handler now emits a Boolean value through the isDismissed behaviour subject.

At this point, the application behaves exactly the way it did before we introduced the Internet Explorer service and the browser service. We have the browser state change commands, but we need some mechanism to trigger them.

For this purpose, we will develop a browser faker component that enables us to fake a browser environment for the rest of the application.

The browser faker component injects the browser service. It has a single form control that is bound to a native

I agree to have my personal information transfered to MailChimp ( more information )

I will never give away, trade or sell your email address. You can unsubscribe at any time.

user

The author didnt add any Information to his profile yet

Loading Posts...