I'm trying to create a spy on a method, that is not known until the target class is instantiated.
Specifically it's about ethers / #projectethers/contract module with Contract class. This class is defined as
export class Contract extends BaseContract {
// The meta-class properties
readonly [ key: string ]: ContractFunction | any;
}
In test, I call the const balanceOfSpy = jest.spyOn(Contract, 'balanceOf') but I get Error: Cannot spy the deposit property because it is not a function; undefined given instead
I don't want to mock Contract class itself, I just want to use the spy to assert, that the method was called. I.e. expect(balanceOfSpy).toBeCalled(). Hence mocking the balanceOf method inside mocked Contract class is not wanted.
Related
I am trying to test that a method is called on mount of Vue component. Fairly new to Vue and Typescript.
export default class App extends Vue {
mounted () {
this.deviceId()
this.ipAddress()
this.channel()
this.show()
this.campaign()
this.adUnit()
}
this approach works but I get a warning:
it('mounted methods are called', async () => {
const deviceId = jest.fn()
wrapper = shallowMount(App, {
methods: {
deviceId
}
})
expect(deviceId).toHaveBeenCalled()
})
The error:
console.error node_modules/#vue/test-utils/dist/vue-test-utils.js:1735
[vue-test-utils]: overwriting methods via the `methods` property is deprecated and will be removed in the next major version. There is no clear migration path for the `methods` property - Vue does not support arbitrarily replacement of methods, nor should VTU. To stub a complex method extract it from the component and test it in isolation. Otherwise, the suggestion is to rethink those tests.
I have tried using jest spyOn, but I cannot find a way to access the method;
const spy = jest.spyOn(App.prototype, 'methodName')
wrapper = shallowMount(App)
expect(spy).toHaveBeenCalled()
Gives the following error:
Cannot spy the deviceId property because it is not a function; undefined given instead
The following also doesn't work:
const spy = jest.spyOn(App.methods, 'methodName')
Error:
Property 'methods' does not exist on type 'VueConstructor<Vue>'.ts(2339)
And the following:
const spy = jest.spyOn(App.prototype.methods, 'deviceId')
Error:
Cannot spyOn on a primitive value; undefined given
I have read in places I may need to define an interface for the component but I am not sure how this works with defining functions inside or if it is necessary?
I've been facing the same issue for a few days, but I've found the way of pointing to the correct method when calling jest.spyOn().
It's a bit tricky but you'll find the methods of your class like this:
const spy = jest.spyOn(App.prototype.constructor.options.methods, 'deviceId');
Note that (even if it might seem obvious, just in case) you'll need to do this before wrapping your component, i.e. like this:
const spy = jest.spyOn(App.prototype.constructor.options.methods, 'deviceId');
wrapper = mount(App, { /* Your options go here */ });
By the way, you don't need to define methods property inside options.
Define your method under the property methods. Only then you can access them from the class.
export default class App extends Vue {
methods: {
deviceId(){
console.log("do your stuff")
}
}
}
See here for more examples for the usage of methods
I have a problem while writing tests for Angular using RxJS.
I have a variable which is used as a mocking provider (actions$) which is typed as "Observable". Now I assign an instance of a subclass to it (ReplaySubject). But now the method "next" is unknown (at least in Typescript) because it's not provided by "Observable" as it is from one of the subclasses "Subject".
How can I type my variable "actions$" correctly or how can I cast correctly to fix the error message?
online example: https://ngrx.io/guide/effects/testing
see line 12 vs 41
RxJS implementation
export declare class ReplaySubject<T> extends Subject<T> {
...
}
export declare class Subject<T> extends Observable<T> implements SubscriptionLike {
...
next(value?: T): void;
...
}
my code
let actions$: Observable<any>;
actions$ = new ReplaySubject(1);
// Property 'next' does not exist on type 'Observable<any>'.
actions$.next(new someThing());
You should type actions$ as Subject<any> or—if you want even more specificity—ReplySubject<any>. Subject extends Observable, so it will work for hot and cold functions if you're using jasmine-marbles.
As for the documentation you referenced, I suspect the actions being typed as Observable is a mistake in print.
class myClass extends React.Component {
async componentDidMount(){
const xyz = helperclass.queryParameters('parameter')
// how can I mock xyz to help me change the value to test the conditional below
if(xyz){
// do something here
}
}
}
have edited the code above, now I want to test the const xyz to the value of the helper function by mocking it out and then returning different things to test if the stuff inside the conditional was done
Since, myFunctionToMock is prototype method, it can be mocked as
jest.spyOn(MyClass.prototype, 'myFunctionToMock').mockImplementation(...);
before class instantiation.
Another option in Enzyme is to disable hooks with disableLifecycleMethods option, mock a method on wrapper.instance() and call componentDidMount manually.
If a method doesn't belong to this, it can be mocked on an object it belongs to:
jest.spyOn( helperclass, 'queryParameters').mockImplementation(...);
Again, this should be done before class instantiation, or disableLifecycleMethods needs to be used.
Assume the following class
class Car {
constructor() {
this.startEngine()
}
startEngine = () => {
console.log('BRRRM!')
}
}
How do I mock startEngine so I can test if it was called in the constructor?
I somewhere read that I could access startEngine by Car.prototype.startEngine, but this does not seem to be the case as (in my case) Webpack hides the method in the Car function and are only accessible after instantiation (maybe because I defined it as an arrow function).
I am using typescript, gulp build and node.
pre-information:
I have an abstract class say SomeClass and A and B are derived classes of that abstract class i.e. SomeClass. The code wants to create an instance of the derived class by passing constructor function that returns an instance of Type T.
This is the Relevant information about that function definition
**async getInstances<T extends SomeClass>(typedConstructor: new () => T): Promise<T>
{
return new typedConstructor();
}**
let say I call this function by passing A that is a derived class of that Abstract class i.e. some class.
getInstance(A);
Post Information:
Now after building this code using gulp when I execute it using node this class is supposed to give me an instance of class A. However, it throws an error saying:
Class constructor SomeClass cannot be invoked without new
What grinds my gears is that SomeClass is an Abstract class then why the error is saying to use New for that class.