I am wondering if my approach to the service I am building and testing is the right approach or not. I have always designed my classes to be as encapsulated as possible. So when it came to building my angular services, I built them the same way.
Below is a snippet of how my service looks:
private postUrl = 'https://localhost:44359/api/posts';
private currentGetPostsUrl = `${this.postUrl}?page=${this.pageNumber}&pageSize=${this.pageSize}`;
private filteredPostListSource = new Subject<IPostViewDto[]>();
filteredPostList$ = this.filteredPostListSource.asObservable();
// post list returned from the api
private originalPostList: IPostViewDto[];
// filtered list that is displayed to user
private filteredPostList: IPostViewDto[];
//get a list of posts that are paginated
getPosts(): Observable < IPostViewDto[] > {
const urlToFetch = `${this.postUrl}?page=${this.pageNumber}&pageSize=${this.pageSize}`;
// if the post list exists, return that post list
if(this.originalPostList) {
return of(this.originalPostList);
}
return this.http.get<IPostViewDto[]>(urlToFetch, { observe: 'response' })
.pipe(
map((response: HttpResponse<IPostViewDto[]>) => {
const paginationHeader = JSON.parse(response.headers.get('X-Pagination'));
this.totalCount = paginationHeader.totalCount;
this.originalPostList = response.body;
this.filteredPostList = [...this.originalPostList];
return response.body;
}),
catchError(err => this.errorHandler(err))
);
}
Per above, I don't allow components to directly access the private variables and instead have methods through which all interaction is done. The issue here is that unit testing is a bit of a mess. If I want to correctly test that my getPosts() method correctly returns the list of posts in my originalPostList if it exists, I'd have to run it once after creating a stub value for the http get to ensure the private field gets set, then run it again and compare my stub value equals the 2nd run of getPosts().
This seems like its not only a bad unit test, but maybe the service itself is not built correctly to be tested.
What would be the best way to restructure this to be easily testable? Do I just create getters/setters and test against those? Or is my approach I described above valid?
Do note that the reason why I designed it this way is because I didn't want child components / other components to accidentally update these properties without an explicit method call (so that I can write tests to ensure that is the case). Its not because a single component is the only one accessing this service.