Gut icon indicating copy to clipboard operation
Gut copied to clipboard

How to create partial_double of WebSocketClient?

Open token-cjg opened this issue 2 years ago • 4 comments

Thanks for writing this marvelous testing library!

GUT version: 7.3.0 Godot version: 3.4.3 (MacOS)

Description

According to https://github.com/bitwes/Gut/wiki/Doubles#doubling-built-ins, I gather that one can do things like this:

var partial_doubled_raycast = partial_double(Raycast2D).new()

and then stub / mock methods accordingly. Indeed if I write a test with GUT 7.3.0 this all works.

However, if I try this for WebSocketClient in Godot 3.4.3

var partial_doubled_websocketclient = partial_double(WebSocketClient).new()

and then try running the GUT test harness, the build crashes.

Hypothesis

I understand that RayCast2D inherits from Node, but WebSocketClient inherits from Reference.

Is it the case that only built-ins that inherit from Node can be mocked at present?

token-cjg avatar Jun 20 '22 20:06 token-cjg

This appears to be a bug. The doubler is having issues the two parameters with PoolStringArray defaults in connect_url:

 Error connect_to_url(url: String, protocols: PoolStringArray = PoolStringArray(  ), gd_mp_api: bool = false, custom_headers: PoolStringArray = PoolStringArray(  ))

I tried all the tricks I could think of to get around this. I tried stubbing the param_count and param_defaults. I also tried using ignore_method_when_doubling. I believe the issue with these approaches is that they are only compatible with scripts and scenes.

The Error

Debugger Break, Reason: 'Parser Error: Error parsing expression, misplaced: ']''
*Frame 0 - :59 in function ''
Enter "help" for assistance.
debug> 

I got the source for the double that was being generated. This is the problem line:

func connect_to_url(p_url=__gut_default_val("connect_to_url",0), p_protocols=Null[], p_gd_mp_api=false, p_custom_headers=Null[]):

Which makes sense because Null[] is not valid GDScript.

Hacky Workaround

If you change _get_arg_text in res://addons/gut/method_maker.gd by adding text = text.replace('Null[]', '[]') it looks like it works.

func _get_arg_text(arg_array):
	var text = ''

	for i in range(arg_array.size()):
		text += str(arg_array[i].p_name, '=', arg_array[i].default)
		if(i != arg_array.size() -1):
			text += ', '
	text = text.replace('Null[]', '[]') # <------ add this line
	return text

I was able to get the test below to pass after making the change. I don't know if it will work if you stub the method to_call_super, but it should work for spying or if you don't need to test this method's usage.

func test_make_websocket_partial_double():
	var WebSocketClientPD = partial_double(WebSocketClient)
	assert_not_null(WebSocketClientPD)
	var pd = WebSocketClientPD.new()
	assert_not_null(pd)

Beware, this is a SUPER HACK and I didn't really test it at all. But it might work until I can figure out how to really solve the issue.

Note to self, add gut.get_doubler()._print_source = true in a test to make GUT spit out the source code for a double. I'll forget how to do this again, but at least it's documented here where I'm sure to forget it.

bitwes avatar Jun 21 '22 04:06 bitwes

P.S. you are welcome, thanks for using GUT!

bitwes avatar Jun 21 '22 04:06 bitwes

This is in the next release and will be closed when that release goes live.

bitwes avatar Jun 21 '22 14:06 bitwes

Thanks for the quick response!

By the way if you are interested, this is the code I managed to get working after applying the fix in your above comment.

Code under test

func obtain_packet(_client: WebSocketClient) -> String:
	var peer: WebSocketPeer = _client.get_peer(1)
	var packet: PoolByteArray = peer.get_packet()
	return packet.get_string_from_utf8()

Test case

func test_obtain_packet():
	var packet: PoolByteArray = PoolByteArray([85, 115, 101]) # Utf8 for 'Use'
	var partial_doubled_peer = partial_double(WebSocketPeer).new()
	var partial_doubled_websocketclient = partial_double(WebSocketClient).new()
	stub(partial_doubled_websocketclient, 'get_peer').to_return(partial_doubled_peer)
	stub(partial_doubled_peer, 'get_packet').to_return(packet)
	var obtained_packet = _webrtc_client.obtain_packet(partial_doubled_websocketclient)
	assert_called(partial_doubled_websocketclient, 'get_peer')
	assert_called(partial_doubled_peer, 'get_packet')
	assert_eq(obtained_packet, 'Use', "Obtained packet should have been 'Use'")

token-cjg avatar Jun 21 '22 19:06 token-cjg

Released in 7.4.0

bitwes avatar Aug 13 '22 20:08 bitwes