Jasmine's spyOn is good to change a method's behavior, but is there any way to change a value property (rather than a method) for an object? the code could be like below:
spyOn(myObj, 'valueA').andReturn(1); expect(myObj.valueA).toBe(1); Jasmine's spyOn is good to change a method's behavior, but is there any way to change a value property (rather than a method) for an object? the code could be like below:
spyOn(myObj, 'valueA').andReturn(1); expect(myObj.valueA).toBe(1); In February 2017, they merged a PR adding this feature, they released in April 2017.
so to spy on getters/setters you use: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); where myObj is your instance, 'myGetterName' is the name of that one defined in your class as get myGetterName() {} and the third param is the type get or set.
You can use the same assertions that you already use with the spies created with spyOn.
So you can for example:
const spy = spyOnProperty(myObj, 'myGetterName', 'get'); // to stub and return nothing. Just spy and stub. const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.returnValue(1); // to stub and return 1 or any value as needed. const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.callThrough(); // Call the real thing. Here's the line in the github source code where this method is available if you are interested.
Answering the original question, with jasmine 2.6.1, you would:
const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1); expect(myObj.valueA).toBe(1); expect(spy).toHaveBeenCalled(); Jasmine doesn't have that functionality, but you might be able to hack something together using Object.defineProperty.
You could refactor your code to use a getter function, then spy on the getter.
spyOn(myObj, 'getValueA').andReturn(1); expect(myObj.getValueA()).toBe(1); Any reason you cannot just change it on the object directly? It is not as if javascript enforces visibility of a property on an object.
If you are using ES6 (Babel) or TypeScript you can stub out the property using get and set accessors
export class SomeClassStub { getValueA = jasmine.createSpy('getValueA'); setValueA = jasmine.createSpy('setValueA'); get valueA() { return this.getValueA(); } set valueA(value) { this.setValueA(value); } } Then in your test you can check that the property is set with:
stub.valueA = 'foo'; expect(stub.setValueA).toHaveBeenCalledWith('foo'); Suppose there is a method like this that needs testing The src property of the tiny image needs checking
function reportABCEvent(cat, type, val) { var i1 = new Image(1, 1); var link = getABC('creosote'); link += "&category=" + String(cat); link += "&event_type=" + String(type); link += "&event_value=" + String(val); i1.src = link; } The spyOn() below causes the "new Image" to be fed the fake code from the test the spyOn code returns an object that only has a src property
As the variable "hook" is scoped to be visible in the fake code in the SpyOn and also later after the "reportABCEvent" is called
describe("Alphabetic.ads", function() { it("ABC events create an image request", function() { var hook={}; spyOn(window, 'Image').andCallFake( function(x,y) { hook={ src: {} } return hook; } ); reportABCEvent('testa', 'testb', 'testc'); expect(hook.src). toEqual('[zubzub]&arg1=testa&arg2=testb&event_value=testc'); }); This is for jasmine 1.3 but might work on 2.0 if the "andCallFake" is altered to the 2.0 name
I'm using a kendo grid and therefore can't change the implementation to a getter method but I want to test around this (mocking the grid) and not test the grid itself. I was using a spy object but this doesn't support property mocking so I do this:
this.$scope.ticketsGrid = { showColumn: jasmine.createSpy('showColumn'), hideColumn: jasmine.createSpy('hideColumn'), select: jasmine.createSpy('select'), dataItem: jasmine.createSpy('dataItem'), _data: [] } It's a bit long winded but it works a treat
I'm a bit late to the party here i know but,
You could directly access the calls object, which can give you the variables for each call
expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue) The best way is to use spyOnProperty. It expects 3 properties and you need to pass get or set as third property.
const div = fixture.debugElement.query(By.css('.ellipsis-overflow')); // now mock properties spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400); spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400); Here I am setting the get of clientWidth of div.nativeElement object.
You can not mock variable but you can create getter function for it and mock that method in your spec file.