add `addListener` function
update
invokeChange => triggerChange
use spy to test whether a function is called
Merge branch 'dev', add addListener and use spy to test whether a function is called