Skip to content

Commit 21f764c

Browse files
devversionandrewseguin
authored andcommitted
build: report ngOnDestroy exceptions in unti tests (#5036)
Monkey-patches TestBed.resetTestingModule such that any errors that occur during component destruction are thrown instead of silently logged. Also runs TestBed.resetTestingModule after each unit test. Without this patch, the combination of two behaviors is problematic for Angular Material: - TestBed.resetTestingModule catches errors thrown on fixture destruction and logs them without the errors ever being thrown. This means that any component errors that occur in ngOnDestroy can encounter errors silently and still pass unit tests. - TestBed.resetTestingModule is only called *before* a test is run, meaning that even *if* the aforementioned errors were thrown, they would be reported for the wrong test (the test that's about to start, not the test that just finished).
1 parent 3a23d31 commit 21f764c

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

test/karma-test-shim.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,50 @@ function configureTestBed() {
8787

8888
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
8989

90-
testing.TestBed.initTestEnvironment(
90+
var testBed = testing.TestBed.initTestEnvironment(
9191
testingBrowser.BrowserDynamicTestingModule,
9292
testingBrowser.platformBrowserDynamicTesting()
9393
);
94+
95+
patchTestBedToDestroyFixturesAfterEveryTest(testBed);
96+
});
97+
}
98+
99+
/**
100+
* Monkey-patches TestBed.resetTestingModule such that any errors that occur during component
101+
* destruction are thrown instead of silently logged. Also runs TestBed.resetTestingModule after
102+
* each unit test.
103+
*
104+
* Without this patch, the combination of two behaviors is problematic for Angular Material:
105+
* - TestBed.resetTestingModule catches errors thrown on fixture destruction and logs them without
106+
* the errors ever being thrown. This means that any component errors that occur in ngOnDestroy
107+
* can encounter errors silently and still pass unit tests.
108+
* - TestBed.resetTestingModule is only called *before* a test is run, meaning that even *if* the
109+
* aforementioned errors were thrown, they would be reported for the wrong test (the test that's
110+
* about to start, not the test that just finished).
111+
*/
112+
function patchTestBedToDestroyFixturesAfterEveryTest(testBed) {
113+
// Original resetTestingModule function of the TestBed.
114+
var _resetTestingModule = testBed.resetTestingModule;
115+
116+
// Monkey-patch the resetTestingModule to destroy fixtures outside of a try/catch block.
117+
// With https://github.com/angular/angular/commit/2c5a67134198a090a24f6671dcdb7b102fea6eba
118+
// errors when destroying components are no longer causing Jasmine to fail.
119+
testBed.resetTestingModule = function() {
120+
try {
121+
this._activeFixtures.forEach(function (fixture) { fixture.destroy(); });
122+
} finally {
123+
this._activeFixtures = [];
124+
// Regardless of errors or not, run the original reset testing module function.
125+
_resetTestingModule.call(this);
126+
}
127+
};
128+
129+
// Angular's testing package resets the testing module before each test. This doesn't work well
130+
// for us because it doesn't allow developers to see what test actually failed.
131+
// Fixing this by resetting the testing module after each test.
132+
// https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L25
133+
afterEach(function() {
134+
testBed.resetTestingModule();
94135
});
95136
}

0 commit comments

Comments
 (0)