JavaScript Destructor?

JavaScript and client side scripting.

Moderator: General Moderators

Post Reply
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

JavaScript Destructor?

Post by Chris Corbyn »

Is there a destructor implementation in JavaScript?

I'm writing a Mock object factory and need it to inject some sort of destructor method to work nicely.

At the moment you can provide expectOnce() type assertions on the Mock but the problem is that they will try to run at the time you call them rather than later so you need to call expectOnce() *after* any operations were done on the mock. If I could have it just set something up and then check once the object destructs it would allow the call to be made anywhere. Unless there's perhaps a better way than my current approach?

Here's how it works at the moment:

Code: Select all

function interfaceToMock()
{
    this.someMethod = function() {}
    this.anotherMethod = function() {}
}

Code: Select all

function myTestCase()
{
    this.testMockRunsACertainMethod = function()
    {
        var mockfactory = new Mock(new interfaceToMock());
        var myMock = mockfactory.generate('myMockName');
        myMock.setReturnValue('someMethod', 42);
        this.assertEqual(42, myMock.someMethod());
        myMock.expectOnce('someMethod'); //Works because we ran it earlier
    }
}

myTestCase.prototype = new UnitTestCase();
myTestCase.run(new DefaultRunner());
and the factory code:

Code: Select all

function Mock(theClass)
{
	this.generate = function(name, testcase)
	{
		var mockObj = new Object();
		mockObj._retvals = new Array();
		mockObj._calls = new Array();
		mockObj._testcase = testcase;
		
		mockObj.setReturnValue = function(f, v)
		{
			mockObj._retvals[f] = v;
		}
		
		mockObj.expectOnce = function(f)
		{
			if (mockObj._calls[f] != 1)
			{
				throw new JSTesterException('Mock expectOnce assertion failed with count ' + mockObj._calls[f]);
			}
			else
			{
				mockObj._testcase.pass('Mock expectOnce passed, OK');
			}
		}
		
		for (var _x in theClass)
		{
			if (typeof theClass[_x] == 'function')
			{
				mockObj._retvals[_x] = null;
				mockObj._calls[_x] = 0;
				
				mockObj[_x] = function()
				{
					if (Mock.isGenerated(name, _x))
					{
						mockObj._calls[_x]++;
						return mockObj._retvals[_x];
					}
					else
					{
						Mock.setGenerated(name, _x);
					}
				}
			}
		}
		
		return mockObj;
	}
}

Mock._completelyGenerated = new Array();
Mock.setGenerated = function(n, f)
{
	if (typeof this._completelyGenerated[n] == 'undefined')
	{
		this._completelyGenerated[n] = new Array();
	}
	this._completelyGenerated[n][f] = true;
}
Mock.isGenerated = function(n, f)
{
	if (typeof this._completelyGenerated[n] == 'undefined') return false;
	else
	{
		if (typeof this._completelyGenerated[n][f] != 'undefined') return true;
	}
}
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Re: JavaScript Destructor?

Post by feyd »

d11wtq wrote:Is there a destructor implementation in JavaScript?
Unless something's changed somewhat recently, no.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Do you think it's a bad thing if the expects calls need to be made after any operations were run on the mock?
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

Do you think it's a bad thing if the expects calls need to be made after any operations were run on the mock?
I think it's somewhat misleading. Though you may name them like 'assertCallCount'...
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Weirdan wrote:
Do you think it's a bad thing if the expects calls need to be made after any operations were run on the mock?
I think it's somewhat misleading. Though you may name them like 'assertCallCount'...
Yeah I might do that thanks.

assertCallCount()
assertCalledOnce()
assertCalledAtLeastOnce()
assertCalledNever()

I'll post back if I run into any other issues :)

EDIT | I'd actually like to come up with a clean way of generating mocked events too like:

Code: Select all

    this.testActionRunsOnMouseover = function()
    {
        var myMock = mockFactory.generate('MockMyObj');

        var someDiv = document.createElement('div');

        someDiv.onmouseover = myMock.doSomething;
        
        var mockMouseover = new MockEvent('MOUSEOVER');
        mockMouseover.setX(200);
        mockMouseover.setY(100);
        mockMouseover.attachTo(someDiv);
        mockMouseover.tigger();

        myMock.assertCalledOnce('doSomething');
    }
Post Reply