1148 lines
37 KiB
GDScript
1148 lines
37 KiB
GDScript
class_name GdUnitMockerTest
|
|
extends GdUnitTestSuite
|
|
|
|
|
|
var resource_path := "res://addons/gdUnit4/test/mocker/resources/"
|
|
|
|
var _saved_report_error_settings
|
|
|
|
|
|
func before():
|
|
# disable error pushing for testing
|
|
_saved_report_error_settings = ProjectSettings.get_setting(GdUnitSettings.REPORT_PUSH_ERRORS)
|
|
ProjectSettings.set_setting(GdUnitSettings.REPORT_PUSH_ERRORS, false)
|
|
|
|
|
|
func after():
|
|
ProjectSettings.set_setting(GdUnitSettings.REPORT_PUSH_ERRORS, _saved_report_error_settings)
|
|
|
|
|
|
func test_mock_instance_id_is_unique():
|
|
var m1 = mock(RefCounted)
|
|
var m2 = mock(RefCounted)
|
|
# test the internal instance id is unique
|
|
assert_that(m1.__instance_id()).is_not_equal(m2.__instance_id())
|
|
assert_object(m1).is_not_same(m2)
|
|
|
|
|
|
func test_is_mockable_godot_classes():
|
|
# verify enigne classes
|
|
for clazz_name in ClassDB.get_class_list():
|
|
# mocking is not allowed for:
|
|
# singleton classes
|
|
# unregistered classes in ClassDB
|
|
# protected classes (name starts with underscore)
|
|
var is_mockable :bool = not Engine.has_singleton(clazz_name) and ClassDB.can_instantiate(clazz_name) and clazz_name.find("_") != 0
|
|
assert_that(GdUnitMockBuilder.is_mockable(clazz_name)) \
|
|
.override_failure_message("Class '%s' expect mockable %s" % [clazz_name, is_mockable]) \
|
|
.is_equal(is_mockable)
|
|
|
|
|
|
func test_is_mockable_by_class_type():
|
|
assert_that(GdUnitMockBuilder.is_mockable(Node)).is_true()
|
|
assert_that(GdUnitMockBuilder.is_mockable(CSGBox3D)).is_true()
|
|
|
|
|
|
func test_is_mockable_custom_class_type():
|
|
assert_that(GdUnitMockBuilder.is_mockable(CustomResourceTestClass)).is_true()
|
|
assert_that(GdUnitMockBuilder.is_mockable(CustomNodeTestClass)).is_true()
|
|
|
|
|
|
func test_is_mockable_by_script_path():
|
|
assert_that(GdUnitMockBuilder.is_mockable(resource_path + "CustomResourceTestClass.gd")).is_true()
|
|
assert_that(GdUnitMockBuilder.is_mockable(resource_path + "CustomNodeTestClass.gd")).is_true()
|
|
# verify for non scripts
|
|
assert_that(GdUnitMockBuilder.is_mockable(resource_path + "capsuleshape2d.tres")).is_false()
|
|
|
|
|
|
func test_is_mockable__overriden_func_get_class():
|
|
# test with class type
|
|
assert_that(GdUnitMockBuilder.is_mockable(OverridenGetClassTestClass))\
|
|
.override_failure_message("The class 'CustomResourceTestClass' should be mockable when 'func get_class()' is overriden")\
|
|
.is_true()
|
|
# test with resource path
|
|
assert_that(GdUnitMockBuilder.is_mockable(resource_path + "OverridenGetClassTestClass.gd"))\
|
|
.override_failure_message("The class 'CustomResourceTestClass' should be mockable when 'func get_class()' is overriden")\
|
|
.is_true()
|
|
|
|
|
|
@warning_ignore("unused_parameter")
|
|
func test_mock_godot_class_fullcheck(fuzzer=GodotClassNameFuzzer.new(), fuzzer_iterations=200):
|
|
var clazz_name = fuzzer.next_value()
|
|
# try to create a mock
|
|
if GdUnitMockBuilder.is_mockable(clazz_name):
|
|
var m = mock(clazz_name, CALL_REAL_FUNC)
|
|
assert_that(m)\
|
|
.override_failure_message("The class %s should be mockable" % clazz_name)\
|
|
.is_not_null()
|
|
|
|
|
|
func test_mock_by_script_path():
|
|
assert_that(mock(resource_path + "CustomResourceTestClass.gd")).is_not_null()
|
|
assert_that(mock(resource_path + "CustomNodeTestClass.gd")).is_not_null()
|
|
|
|
|
|
func test_mock_class__overriden_func_get_class():
|
|
assert_that(mock(OverridenGetClassTestClass)).is_not_null()
|
|
assert_that(mock(resource_path + "OverridenGetClassTestClass.gd")).is_not_null()
|
|
|
|
|
|
func test_mock_fail():
|
|
# not godot class
|
|
assert_that(mock("CustomResourceTestClass")).is_null()
|
|
# invalid path to script
|
|
assert_that(mock("invalid/CustomResourceTestClass.gd")).is_null()
|
|
# try to mocking an existing instance is not allowed
|
|
assert_that(mock(CustomResourceTestClass.new())).is_null()
|
|
|
|
|
|
func test_mock_special_classes():
|
|
var m = mock("JavaClass") as JavaClass
|
|
assert_that(m).is_not_null()
|
|
|
|
|
|
func test_mock_Node():
|
|
var mocked_node = mock(Node)
|
|
assert_that(mocked_node).is_not_null()
|
|
|
|
# test we have initial no interactions checked this mock
|
|
verify_no_interactions(mocked_node)
|
|
|
|
# verify we have never called 'get_child_count()'
|
|
verify(mocked_node, 0).get_child_count()
|
|
|
|
# call 'get_child_count()' once
|
|
mocked_node.get_child_count()
|
|
# verify we have called at once
|
|
verify(mocked_node).get_child_count()
|
|
|
|
# call function 'get_child_count' a second time
|
|
mocked_node.get_child_count()
|
|
# verify we have called at twice
|
|
verify(mocked_node, 2).get_child_count()
|
|
|
|
# test mocked function returns default typed value
|
|
assert_that(mocked_node.get_child_count()).is_equal(0)
|
|
# now mock return value for function 'foo' to 'overwriten value'
|
|
do_return(24).on(mocked_node).get_child_count()
|
|
# verify the return value is overwritten
|
|
assert_that(mocked_node.get_child_count()).is_equal(24)
|
|
|
|
|
|
func test_mock_source_with_class_name_by_resource_path() -> void:
|
|
var resource_path_ := 'res://addons/gdUnit4/test/mocker/resources/GD-256/world.gd'
|
|
var m = mock(resource_path_)
|
|
var head :String = m.get_script().source_code.substr(0, 200)
|
|
assert_str(head)\
|
|
.contains("class_name DoubledMunderwoodPathingWorld")\
|
|
.contains("extends '%s'" % resource_path_)
|
|
|
|
|
|
func test_mock_source_with_class_name_by_class() -> void:
|
|
var resource_path_ := 'res://addons/gdUnit4/test/mocker/resources/GD-256/world.gd'
|
|
var m = mock(Munderwood_Pathing_World)
|
|
var head :String = m.get_script().source_code.substr(0, 200)
|
|
assert_str(head)\
|
|
.contains("class_name DoubledMunderwoodPathingWorld")\
|
|
.contains("extends '%s'" % resource_path_)
|
|
|
|
|
|
func test_mock_extends_godot_class() -> void:
|
|
var m = mock(World3D)
|
|
var head :String = m.get_script().source_code.substr(0, 200)
|
|
assert_str(head)\
|
|
.contains("class_name DoubledWorld")\
|
|
.contains("extends World3D")
|
|
|
|
|
|
var _test_signal_args := Array()
|
|
func _emit_ready(a, b, c = null):
|
|
_test_signal_args = [a, b, c]
|
|
|
|
|
|
func test_mock_Node_func_vararg():
|
|
# setup
|
|
var mocked_node = mock(Node)
|
|
|
|
# mock return value
|
|
do_return(ERR_CANT_CONNECT).on(mocked_node).rpc("test", "arg1", "arg2", "invalid")
|
|
do_return(ERR_CANT_OPEN).on(mocked_node).rpc("test", "arg1", "argX", any_string())
|
|
do_return(ERR_CANT_CREATE).on(mocked_node).rpc("test", "arg1", "argX", any_int())
|
|
do_return(OK).on(mocked_node).rpc("test", "arg1", "argX", "arg3")
|
|
# verify
|
|
assert_that(mocked_node.rpc("test", "arg1", "arg2", "arg3")).is_equal(OK)
|
|
assert_that(mocked_node.rpc("test", "arg1", "arg2", "invalid")).is_equal(ERR_CANT_CONNECT)
|
|
assert_that(mocked_node.rpc("test", "arg1", "argX", "arg3")).is_equal(OK)
|
|
assert_that(mocked_node.rpc("test", "arg1", "argX", "other")).is_equal(ERR_CANT_OPEN)
|
|
assert_that(mocked_node.rpc("test", "arg1", "argX", 42)).is_equal(ERR_CANT_CREATE)
|
|
|
|
|
|
func test_mock_Node_func_vararg_call_real_func():
|
|
# setup
|
|
var mocked_node = mock(Node, CALL_REAL_FUNC)
|
|
assert_that(mocked_node).is_not_null()
|
|
assert_that(_test_signal_args).is_empty()
|
|
mocked_node.connect("ready", _emit_ready)
|
|
|
|
# test emit it
|
|
mocked_node.emit_signal("ready", "aa", "bb", "cc")
|
|
|
|
# verify is emitted
|
|
verify(mocked_node).emit_signal("ready", "aa", "bb", "cc")
|
|
await get_tree().process_frame
|
|
assert_that(_test_signal_args).is_equal(["aa", "bb", "cc"])
|
|
|
|
# test emit it
|
|
mocked_node.emit_signal("ready", "aa", "xxx")
|
|
|
|
# verify is emitted
|
|
verify(mocked_node).emit_signal("ready", "aa", "xxx")
|
|
await get_tree().process_frame
|
|
assert_that(_test_signal_args).is_equal(["aa", "xxx", null])
|
|
|
|
|
|
class ClassWithSignal:
|
|
signal test_signal_a
|
|
signal test_signal_b
|
|
|
|
func foo(arg :int) -> void:
|
|
if arg == 0:
|
|
emit_signal("test_signal_a", "aa")
|
|
else:
|
|
emit_signal("test_signal_b", "bb", true)
|
|
|
|
func bar(arg :int) -> bool:
|
|
if arg == 0:
|
|
emit_signal("test_signal_a", "aa")
|
|
else:
|
|
emit_signal("test_signal_b", "bb", true)
|
|
return true
|
|
|
|
|
|
func _test_mock_verify_emit_signal():
|
|
var mocked_node = mock(ClassWithSignal, CALL_REAL_FUNC)
|
|
assert_that(mocked_node).is_not_null()
|
|
|
|
mocked_node.foo(0)
|
|
verify(mocked_node, 1).emit_signal("test_signal_a", "aa")
|
|
verify(mocked_node, 0).emit_signal("test_signal_b", "bb", true)
|
|
reset(mocked_node)
|
|
|
|
mocked_node.foo(1)
|
|
verify(mocked_node, 0).emit_signal("test_signal_a", "aa")
|
|
verify(mocked_node, 1).emit_signal("test_signal_b", "bb", true)
|
|
reset(mocked_node)
|
|
|
|
mocked_node.bar(0)
|
|
verify(mocked_node, 1).emit_signal("test_signal_a", "aa")
|
|
verify(mocked_node, 0).emit_signal("test_signal_b", "bb", true)
|
|
reset(mocked_node)
|
|
|
|
mocked_node.bar(1)
|
|
verify(mocked_node, 0).emit_signal("test_signal_a", "aa")
|
|
verify(mocked_node, 1).emit_signal("test_signal_b", "bb", true)
|
|
|
|
|
|
func test_mock_custom_class_by_class_name():
|
|
var m = mock(CustomResourceTestClass)
|
|
assert_that(m).is_not_null()
|
|
|
|
# test we have initial no interactions checked this mock
|
|
verify_no_interactions(m)
|
|
# test mocked function returns default typed value
|
|
assert_that(m.foo()).is_equal("")
|
|
|
|
# now mock return value for function 'foo' to 'overwriten value'
|
|
do_return("overriden value").on(m).foo()
|
|
# verify the return value is overwritten
|
|
assert_that(m.foo()).is_equal("overriden value")
|
|
|
|
# now mock return values by custom arguments
|
|
do_return("arg_1").on(m).bar(1)
|
|
do_return("arg_2").on(m).bar(2)
|
|
|
|
assert_that(m.bar(1)).is_equal("arg_1")
|
|
assert_that(m.bar(2)).is_equal("arg_2")
|
|
|
|
|
|
func test_mock_custom_class_by_resource_path():
|
|
var m = mock("res://addons/gdUnit4/test/mocker/resources/CustomResourceTestClass.gd")
|
|
assert_that(m).is_not_null()
|
|
|
|
# test we have initial no interactions checked this mock
|
|
verify_no_interactions(m)
|
|
# test mocked function returns default typed value
|
|
assert_that(m.foo()).is_equal("")
|
|
|
|
# now mock return value for function 'foo' to 'overwriten value'
|
|
do_return("overriden value").on(m).foo()
|
|
# verify the return value is overwritten
|
|
assert_that(m.foo()).is_equal("overriden value")
|
|
|
|
# now mock return values by custom arguments
|
|
do_return("arg_1").on(m).bar(1)
|
|
do_return("arg_2").on(m).bar(2)
|
|
|
|
assert_that(m.bar(1)).is_equal("arg_1")
|
|
assert_that(m.bar(2)).is_equal("arg_2")
|
|
|
|
|
|
func test_mock_custom_class_func_foo_use_real_func():
|
|
var m = mock(CustomResourceTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
# test mocked function returns value from real function
|
|
assert_that(m.foo()).is_equal("foo")
|
|
# now mock return value for function 'foo' to 'overwriten value'
|
|
do_return("overridden value").on(m).foo()
|
|
# verify the return value is overwritten
|
|
assert_that(m.foo()).is_equal("overridden value")
|
|
|
|
|
|
func test_mock_custom_class_void_func():
|
|
var m = mock(CustomResourceTestClass)
|
|
assert_that(m).is_not_null()
|
|
# test mocked void function returns null by default
|
|
assert_that(m.foo_void()).is_null()
|
|
# try now mock return value for a void function. results into an error
|
|
do_return("overridden value").on(m).foo_void()
|
|
# verify it has no affect for void func
|
|
assert_that(m.foo_void()).is_null()
|
|
|
|
|
|
func test_mock_custom_class_void_func_real_func():
|
|
var m = mock(CustomResourceTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
# test mocked void function returns null by default
|
|
assert_that(m.foo_void()).is_null()
|
|
# try now mock return value for a void function. results into an error
|
|
do_return("overridden value").on(m).foo_void()
|
|
# verify it has no affect for void func
|
|
assert_that(m.foo_void()).is_null()
|
|
|
|
|
|
func test_mock_custom_class_func_foo_call_times():
|
|
var m = mock(CustomResourceTestClass)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).foo()
|
|
m.foo()
|
|
verify(m, 1).foo()
|
|
m.foo()
|
|
verify(m, 2).foo()
|
|
m.foo()
|
|
m.foo()
|
|
verify(m, 4).foo()
|
|
|
|
|
|
func test_mock_custom_class_func_foo_call_times_real_func():
|
|
var m = mock(CustomResourceTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).foo()
|
|
m.foo()
|
|
verify(m, 1).foo()
|
|
m.foo()
|
|
verify(m, 2).foo()
|
|
m.foo()
|
|
m.foo()
|
|
verify(m, 4).foo()
|
|
|
|
|
|
func test_mock_custom_class_func_foo_full_test():
|
|
var m = mock(CustomResourceTestClass)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).foo()
|
|
assert_that(m.foo()).is_equal("")
|
|
verify(m, 1).foo()
|
|
do_return("new value").on(m).foo()
|
|
verify(m, 1).foo()
|
|
assert_that(m.foo()).is_equal("new value")
|
|
verify(m, 2).foo()
|
|
|
|
|
|
func test_mock_custom_class_func_foo_full_test_real_func():
|
|
var m = mock(CustomResourceTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).foo()
|
|
assert_that(m.foo()).is_equal("foo")
|
|
verify(m, 1).foo()
|
|
do_return("new value").on(m).foo()
|
|
verify(m, 1).foo()
|
|
assert_that(m.foo()).is_equal("new value")
|
|
verify(m, 2).foo()
|
|
|
|
|
|
func test_mock_custom_class_func_bar():
|
|
var m = mock(CustomResourceTestClass)
|
|
assert_that(m).is_not_null()
|
|
assert_that(m.bar(10)).is_equal("")
|
|
# verify 'bar' with args [10] is called one time at this point
|
|
verify(m, 1).bar(10)
|
|
# verify 'bar' with args [10, 20] is never called at this point
|
|
verify(m, 0).bar(10, 29)
|
|
# verify 'bar' with args [23] is never called at this point
|
|
verify(m, 0).bar(23)
|
|
|
|
# now mock return value for function 'bar' with args [10] to 'overwriten value'
|
|
do_return("overridden value").on(m).bar(10)
|
|
# verify the return value is overwritten
|
|
assert_that(m.bar(10)).is_equal("overridden value")
|
|
# finally verify function call times
|
|
verify(m, 2).bar(10)
|
|
verify(m, 0).bar(10, 29)
|
|
verify(m, 0).bar(23)
|
|
|
|
|
|
func test_mock_custom_class_func_bar_real_func():
|
|
var m = mock(CustomResourceTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
assert_that(m.bar(10)).is_equal("test_33")
|
|
# verify 'bar' with args [10] is called one time at this point
|
|
verify(m, 1).bar(10)
|
|
# verify 'bar' with args [10, 20] is never called at this point
|
|
verify(m, 0).bar(10, 29)
|
|
# verify 'bar' with args [23] is never called at this point
|
|
verify(m, 0).bar(23)
|
|
|
|
# now mock return value for function 'bar' with args [10] to 'overwriten value'
|
|
do_return("overridden value").on(m).bar(10)
|
|
# verify the return value is overwritten
|
|
assert_that(m.bar(10)).is_equal("overridden value")
|
|
# verify the real implementation is used
|
|
assert_that(m.bar(10, 29)).is_equal("test_39")
|
|
assert_that(m.bar(10, 20, "other")).is_equal("other_30")
|
|
# finally verify function call times
|
|
verify(m, 2).bar(10)
|
|
verify(m, 1).bar(10, 29)
|
|
verify(m, 0).bar(10, 20)
|
|
verify(m, 1).bar(10, 20, "other")
|
|
|
|
|
|
func test_mock_custom_class_func_return_type_enum():
|
|
var m = mock(ClassWithEnumReturnTypes)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).get_enum()
|
|
|
|
# verify enum return default ClassWithEnumReturnTypes.TEST_ENUM.FOO
|
|
assert_that(m.get_enum()).is_equal(ClassWithEnumReturnTypes.TEST_ENUM.FOO)
|
|
do_return(ClassWithEnumReturnTypes.TEST_ENUM.BAR).on(m).get_enum()
|
|
assert_that(m.get_enum()).is_equal(ClassWithEnumReturnTypes.TEST_ENUM.BAR)
|
|
verify(m, 2).get_enum()
|
|
|
|
# with call real functions
|
|
var m2 = mock(ClassWithEnumReturnTypes, CALL_REAL_FUNC)
|
|
assert_that(m2).is_not_null()
|
|
|
|
# verify enum return type
|
|
assert_that(m2.get_enum()).is_equal(ClassWithEnumReturnTypes.TEST_ENUM.FOO)
|
|
do_return(ClassWithEnumReturnTypes.TEST_ENUM.BAR).on(m2).get_enum()
|
|
assert_that(m2.get_enum()).is_equal(ClassWithEnumReturnTypes.TEST_ENUM.BAR)
|
|
|
|
|
|
func test_mock_custom_class_func_return_type_internal_class_enum():
|
|
var m = mock(ClassWithEnumReturnTypes)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).get_inner_class_enum()
|
|
|
|
# verify enum return default
|
|
assert_that(m.get_inner_class_enum()).is_equal(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.FOO)
|
|
do_return(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.BAR).on(m).get_inner_class_enum()
|
|
assert_that(m.get_inner_class_enum()).is_equal(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.BAR)
|
|
verify(m, 2).get_inner_class_enum()
|
|
|
|
# with call real functions
|
|
var m2= mock(ClassWithEnumReturnTypes, CALL_REAL_FUNC)
|
|
assert_that(m2).is_not_null()
|
|
|
|
# verify enum return type
|
|
assert_that(m2.get_inner_class_enum()).is_equal(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.FOO)
|
|
do_return(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.BAR).on(m2).get_inner_class_enum()
|
|
assert_that(m2.get_inner_class_enum()).is_equal(ClassWithEnumReturnTypes.InnerClass.TEST_ENUM.BAR)
|
|
|
|
|
|
func test_mock_custom_class_func_return_type_external_class_enum():
|
|
var m = mock(ClassWithEnumReturnTypes)
|
|
assert_that(m).is_not_null()
|
|
verify(m, 0).get_external_class_enum()
|
|
|
|
# verify enum return default
|
|
assert_that(m.get_external_class_enum()).is_equal(CustomEnums.TEST_ENUM.FOO)
|
|
do_return(CustomEnums.TEST_ENUM.BAR).on(m).get_external_class_enum()
|
|
assert_that(m.get_external_class_enum()).is_equal(CustomEnums.TEST_ENUM.BAR)
|
|
verify(m, 2).get_external_class_enum()
|
|
|
|
# with call real functions
|
|
var m2 = mock(ClassWithEnumReturnTypes, CALL_REAL_FUNC)
|
|
assert_that(m2).is_not_null()
|
|
|
|
# verify enum return type
|
|
assert_that(m2.get_external_class_enum()).is_equal(CustomEnums.TEST_ENUM.FOO)
|
|
do_return(CustomEnums.TEST_ENUM.BAR).on(m2).get_external_class_enum()
|
|
assert_that(m2.get_external_class_enum()).is_equal(CustomEnums.TEST_ENUM.BAR)
|
|
|
|
|
|
func test_mock_custom_class_extends_Node():
|
|
var m = mock(CustomNodeTestClass)
|
|
assert_that(m).is_not_null()
|
|
|
|
# test mocked function returns null as default
|
|
assert_that(m.get_child_count()).is_equal(0)
|
|
assert_that(m.get_children()).contains_exactly([])
|
|
# test seters has no affect
|
|
var node = auto_free(Node.new())
|
|
m.add_child(node)
|
|
assert_that(m.get_child_count()).is_equal(0)
|
|
assert_that(m.get_children()).contains_exactly([])
|
|
verify(m, 1).add_child(node)
|
|
verify(m, 2).get_child_count()
|
|
verify(m, 2).get_children()
|
|
|
|
|
|
func test_mock_custom_class_extends_Node_real_func():
|
|
var m = mock(CustomNodeTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
# test mocked function returns default mock value
|
|
assert_that(m.get_child_count()).is_equal(0)
|
|
assert_that(m.get_children()).is_equal([])
|
|
# test real seters used
|
|
var nodeA = auto_free(Node.new())
|
|
var nodeB = auto_free(Node.new())
|
|
var nodeC = auto_free(Node.new())
|
|
m.add_child(nodeA)
|
|
m.add_child(nodeB)
|
|
assert_that(m.get_child_count()).is_equal(2)
|
|
assert_that(m.get_children()).contains_exactly([nodeA, nodeB])
|
|
verify(m, 1).add_child(nodeA)
|
|
verify(m, 1).add_child(nodeB)
|
|
verify(m, 0).add_child(nodeC)
|
|
verify(m, 2).get_child_count()
|
|
verify(m, 2).get_children()
|
|
|
|
|
|
func test_mock_custom_class_extends_other_custom_class():
|
|
var m = mock(CustomClassExtendsCustomClass)
|
|
assert_that(mock).is_not_null()
|
|
|
|
# foo() form parent class
|
|
verify(m, 0).foo()
|
|
# foo2() overriden
|
|
verify(m, 0).foo2()
|
|
# bar2() from class
|
|
verify(m, 0).bar2()
|
|
|
|
assert_that(m.foo()).is_empty()
|
|
assert_that(m.foo2()).is_null()
|
|
assert_that(m.bar2()).is_empty()
|
|
|
|
verify(m, 1).foo()
|
|
verify(m, 1).foo2()
|
|
verify(m, 1).bar2()
|
|
|
|
# override returns
|
|
do_return("abc1").on(m).foo()
|
|
do_return("abc2").on(m).foo2()
|
|
do_return("abc3").on(m).bar2()
|
|
|
|
assert_that(m.foo()).is_equal("abc1")
|
|
assert_that(m.foo2()).is_equal("abc2")
|
|
assert_that(m.bar2()).is_equal("abc3")
|
|
|
|
|
|
func test_mock_custom_class_extends_other_custom_class_call_real_func():
|
|
var m = mock(CustomClassExtendsCustomClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
|
|
# foo() form parent class
|
|
verify(m, 0).foo()
|
|
# foo2() overriden
|
|
verify(m, 0).foo2()
|
|
# bar2() from class
|
|
verify(m, 0).bar2()
|
|
|
|
assert_that(m.foo()).is_equal("foo")
|
|
assert_that(m.foo2()).is_equal("foo2 overriden")
|
|
assert_that(m.bar2()).is_equal("test_65")
|
|
|
|
verify(m, 1).foo()
|
|
verify(m, 1).foo2()
|
|
verify(m, 1).bar2()
|
|
|
|
# override returns
|
|
do_return("abc1").on(m).foo()
|
|
do_return("abc2").on(m).foo2()
|
|
do_return("abc3").on(m).bar2()
|
|
|
|
assert_that(m.foo()).is_equal("abc1")
|
|
assert_that(m.foo2()).is_equal("abc2")
|
|
assert_that(m.bar2()).is_equal("abc3")
|
|
|
|
|
|
func test_mock_static_func():
|
|
var m = mock(CustomNodeTestClass)
|
|
assert_that(m).is_not_null()
|
|
# initial not called
|
|
verify(m, 0).static_test()
|
|
verify(m, 0).static_test_void()
|
|
|
|
assert_that(m.static_test()).is_equal("")
|
|
assert_that(m.static_test_void()).is_null()
|
|
|
|
verify(m, 1).static_test()
|
|
verify(m, 1).static_test_void()
|
|
m.static_test()
|
|
m.static_test_void()
|
|
m.static_test_void()
|
|
verify(m, 2).static_test()
|
|
verify(m, 3).static_test_void()
|
|
|
|
|
|
func test_mock_static_func_real_func():
|
|
var m = mock(CustomNodeTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
# initial not called
|
|
verify(m, 0).static_test()
|
|
verify(m, 0).static_test_void()
|
|
|
|
assert_that(m.static_test()).is_equal(CustomNodeTestClass.STATIC_FUNC_RETURN_VALUE)
|
|
assert_that(m.static_test_void()).is_null()
|
|
|
|
verify(m, 1).static_test()
|
|
verify(m, 1).static_test_void()
|
|
m.static_test()
|
|
m.static_test_void()
|
|
m.static_test_void()
|
|
verify(m, 2).static_test()
|
|
verify(m, 3).static_test_void()
|
|
|
|
|
|
func test_mock_custom_class_assert_has_no_side_affect():
|
|
var m = mock(CustomNodeTestClass)
|
|
assert_that(m).is_not_null()
|
|
var node = Node.new()
|
|
# verify the assertions has no side affect checked mocked object
|
|
verify(m, 0).add_child(node)
|
|
# expect no change checked childrens
|
|
assert_that(m.get_children()).contains_exactly([])
|
|
|
|
m.add_child(node)
|
|
# try thre times 'assert_called' to see it has no affect to the mock
|
|
verify(m, 1).add_child(node)
|
|
verify(m, 1).add_child(node)
|
|
verify(m, 1).add_child(node)
|
|
assert_that(m.get_children()).contains_exactly([])
|
|
# needs to be manually freed
|
|
node.free()
|
|
|
|
|
|
func test_mock_custom_class_assert_has_no_side_affect_real_func():
|
|
var m = mock(CustomNodeTestClass, CALL_REAL_FUNC)
|
|
assert_that(m).is_not_null()
|
|
var node = Node.new()
|
|
# verify the assertions has no side affect checked mocked object
|
|
verify(m, 0).add_child(node)
|
|
# expect no change checked childrens
|
|
assert_that(m.get_children()).contains_exactly([])
|
|
|
|
m.add_child(node)
|
|
# try thre times 'assert_called' to see it has no affect to the mock
|
|
verify(m, 1).add_child(node)
|
|
verify(m, 1).add_child(node)
|
|
verify(m, 1).add_child(node)
|
|
assert_that(m.get_children()).contains_exactly([node])
|
|
|
|
|
|
# This test verifies a function is calling other internally functions
|
|
# to collect the access times and the override return value is working as expected
|
|
func test_mock_advanced_func_path():
|
|
var m = mock(AdvancedTestClass, CALL_REAL_FUNC)
|
|
# initial nothing is called
|
|
verify(m, 0).select(AdvancedTestClass.A)
|
|
verify(m, 0).select(AdvancedTestClass.B)
|
|
verify(m, 0).select(AdvancedTestClass.C)
|
|
verify(m, 0).a()
|
|
verify(m, 0).b()
|
|
verify(m, 0).c()
|
|
|
|
# the function select() swiches based checked input argument to function a(), b() or c()
|
|
# call select where called internally func a() and returned "a"
|
|
assert_that(m.select(AdvancedTestClass.A)).is_equal("a")
|
|
# verify when call select() is also calling original func a()
|
|
verify(m, 1).select(AdvancedTestClass.A)
|
|
verify(m, 1).a()
|
|
|
|
# call select again wiht overriden return value for func a()
|
|
do_return("overridden a func").on(m).a()
|
|
assert_that(m.select(AdvancedTestClass.A)).is_equal("overridden a func")
|
|
|
|
# verify at this time select() and a() is called two times
|
|
verify(m, 2).select(AdvancedTestClass.A)
|
|
verify(m, 0).select(AdvancedTestClass.B)
|
|
verify(m, 0).select(AdvancedTestClass.C)
|
|
verify(m, 2).a()
|
|
verify(m, 0).b()
|
|
verify(m, 0).c()
|
|
|
|
# finally use select to switch to internally func c()
|
|
assert_that(m.select(AdvancedTestClass.C)).is_equal("c")
|
|
verify(m, 2).select(AdvancedTestClass.A)
|
|
verify(m, 0).select(AdvancedTestClass.B)
|
|
verify(m, 1).select(AdvancedTestClass.C)
|
|
verify(m, 2).a()
|
|
verify(m, 0).b()
|
|
verify(m, 1).c()
|
|
|
|
|
|
func _test_mock_godot_class_calls_sub_function():
|
|
var m = mock(MeshInstance3D, CALL_REAL_FUNC)
|
|
verify(m, 0)._mesh_changed()
|
|
m.set_mesh(QuadMesh.new())
|
|
verify(m, 1).set_mesh(any_class(Mesh))
|
|
verify(m, 1)._mesh_changed()
|
|
|
|
|
|
func test_mock_class_with_inner_classs():
|
|
var mock_advanced = mock(AdvancedTestClass)
|
|
assert_that(mock_advanced).is_not_null()
|
|
|
|
var mock_a := mock(AdvancedTestClass.SoundData) as AdvancedTestClass.SoundData
|
|
assert_object(mock_a).is_not_null()
|
|
|
|
var mock_b := mock(AdvancedTestClass.AtmosphereData) as AdvancedTestClass.AtmosphereData
|
|
assert_object(mock_b).is_not_null()
|
|
|
|
var mock_c := mock(AdvancedTestClass.Area4D) as AdvancedTestClass.Area4D
|
|
assert_object(mock_c).is_not_null()
|
|
|
|
|
|
func test_do_return():
|
|
var mocked_node = mock(Node)
|
|
|
|
# is return 0 by default
|
|
mocked_node.get_child_count()
|
|
# configure to return 10 when 'get_child_count()' is called
|
|
do_return(10).on(mocked_node).get_child_count()
|
|
# will now return 10
|
|
assert_int(mocked_node.get_child_count()).is_equal(10)
|
|
|
|
# is return 'null' by default
|
|
var node = mocked_node.get_child(0)
|
|
assert_object(node).is_null()
|
|
|
|
# configure to return a mocked 'Camera3D' for child 0
|
|
do_return(mock(Camera3D)).on(mocked_node).get_child(0)
|
|
# configure to return a mocked 'Area3D' for child 1
|
|
do_return(mock(Area3D)).on(mocked_node).get_child(1)
|
|
|
|
# will now return the Camera3D node
|
|
var node0 = mocked_node.get_child(0)
|
|
assert_object(node0).is_instanceof(Camera3D)
|
|
# will now return the Area3D node
|
|
var node1 = mocked_node.get_child(1)
|
|
assert_object(node1).is_instanceof(Area3D)
|
|
|
|
|
|
func test_matching_is_sorted():
|
|
var mocked_node = mock(Node)
|
|
do_return(null).on(mocked_node).get_child(any(), false)
|
|
do_return(null).on(mocked_node).get_child(1, false)
|
|
do_return(null).on(mocked_node).get_child(10, false)
|
|
do_return(null).on(mocked_node).get_child(any(), true)
|
|
do_return(null).on(mocked_node).get_child(3, true)
|
|
|
|
# get the sorted mocked args as array
|
|
var mocked_args :Array = mocked_node.__mocked_return_values.get("get_child").keys()
|
|
assert_array(mocked_args).has_size(5)
|
|
|
|
# we expect all argument matchers are sorted to the end
|
|
var first_arguments = mocked_args.map(func (v): return v[0])
|
|
assert_int(first_arguments[0]).is_equal(3)
|
|
assert_int(first_arguments[1]).is_equal(10)
|
|
assert_int(first_arguments[2]).is_equal(1)
|
|
assert_object(first_arguments[3]).is_instanceof(GdUnitArgumentMatcher)
|
|
assert_object(first_arguments[4]).is_instanceof(GdUnitArgumentMatcher)
|
|
|
|
|
|
func test_do_return_with_matchers():
|
|
var mocked_node = mock(Node)
|
|
var childN :Node = auto_free(Node2D.new())
|
|
var child1 :Node = auto_free(Node2D.new())
|
|
var child10 :Node = auto_free(Node2D.new())
|
|
|
|
# for any index return childN by using any() matcher
|
|
do_return(childN).on(mocked_node).get_child(any(), false)
|
|
# for index 1 and 10 do return 'child1' and 'child10'
|
|
do_return(child1).on(mocked_node).get_child(1, false)
|
|
do_return(child10).on(mocked_node).get_child(10, false)
|
|
# for any index and flag true, we return null by using the 'any_int' matcher
|
|
do_return(null).on(mocked_node).get_child(any_int(), true)
|
|
|
|
assert_that(mocked_node.get_child(0, true)).is_null()
|
|
assert_that(mocked_node.get_child(1, true)).is_null()
|
|
assert_that(mocked_node.get_child(2, true)).is_null()
|
|
assert_that(mocked_node.get_child(10, true)).is_null()
|
|
assert_that(mocked_node.get_child(0)).is_same(childN)
|
|
assert_that(mocked_node.get_child(1)).is_same(child1)
|
|
assert_that(mocked_node.get_child(2)).is_same(childN)
|
|
assert_that(mocked_node.get_child(3)).is_same(childN)
|
|
assert_that(mocked_node.get_child(4)).is_same(childN)
|
|
assert_that(mocked_node.get_child(5)).is_same(childN)
|
|
assert_that(mocked_node.get_child(6)).is_same(childN)
|
|
assert_that(mocked_node.get_child(7)).is_same(childN)
|
|
assert_that(mocked_node.get_child(8)).is_same(childN)
|
|
assert_that(mocked_node.get_child(9)).is_same(childN)
|
|
assert_that(mocked_node.get_child(10)).is_same(child10)
|
|
|
|
|
|
func test_example_verify():
|
|
var mocked_node = mock(Node)
|
|
|
|
# verify we have no interactions currently checked this instance
|
|
verify_no_interactions(mocked_node)
|
|
|
|
# call with different arguments
|
|
mocked_node.set_process(false) # 1 times
|
|
mocked_node.set_process(true) # 1 times
|
|
mocked_node.set_process(true) # 2 times
|
|
|
|
# verify how often we called the function with different argument
|
|
verify(mocked_node, 2).set_process(true) # in sum two times with true
|
|
verify(mocked_node, 1).set_process(false)# in sum one time with false
|
|
|
|
# verify total sum by using an argument matcher
|
|
verify(mocked_node, 3).set_process(any_bool())
|
|
|
|
|
|
func test_verify_fail():
|
|
var mocked_node = mock(Node)
|
|
|
|
# interact two time
|
|
mocked_node.set_process(true) # 1 times
|
|
mocked_node.set_process(true) # 2 times
|
|
|
|
# verify we interacts two times
|
|
verify(mocked_node, 2).set_process(true)
|
|
|
|
# verify should fail because we interacts two times and not one
|
|
var expected_error := """
|
|
Expecting interaction on:
|
|
'set_process(true :bool)' 1 time's
|
|
But found interactions on:
|
|
'set_process(true :bool)' 2 time's""" \
|
|
.dedent().trim_prefix("\n").replace("\r", "")
|
|
assert_failure(func(): verify(mocked_node, 1).set_process(true)) \
|
|
.is_failed() \
|
|
.has_message(expected_error)
|
|
|
|
|
|
func test_verify_func_interaction_wiht_PoolStringArray():
|
|
var mocked = mock(ClassWithPoolStringArrayFunc)
|
|
|
|
mocked.set_values(PackedStringArray())
|
|
|
|
verify(mocked).set_values(PackedStringArray())
|
|
verify_no_more_interactions(mocked)
|
|
|
|
|
|
func test_verify_func_interaction_wiht_PoolStringArray_fail():
|
|
var mocked = mock(ClassWithPoolStringArrayFunc)
|
|
|
|
mocked.set_values(PackedStringArray())
|
|
|
|
# try to verify with default array type instead of PackedStringArray type
|
|
var expected_error := """
|
|
Expecting interaction on:
|
|
'set_values([] :Array)' 1 time's
|
|
But found interactions on:
|
|
'set_values([] :PackedStringArray)' 1 time's""" \
|
|
.dedent().trim_prefix("\n").replace("\r", "")
|
|
assert_failure(func(): verify(mocked, 1).set_values([])) \
|
|
.is_failed() \
|
|
.has_message(expected_error)
|
|
|
|
reset(mocked)
|
|
# try again with called two times and different args
|
|
mocked.set_values(PackedStringArray())
|
|
mocked.set_values(PackedStringArray(["a", "b"]))
|
|
mocked.set_values([1, 2])
|
|
expected_error = """
|
|
Expecting interaction on:
|
|
'set_values([] :Array)' 1 time's
|
|
But found interactions on:
|
|
'set_values([] :PackedStringArray)' 1 time's
|
|
'set_values(["a", "b"] :PackedStringArray)' 1 time's
|
|
'set_values([1, 2] :Array)' 1 time's""" \
|
|
.dedent().trim_prefix("\n").replace("\r", "")
|
|
assert_failure(func(): verify(mocked, 1).set_values([])) \
|
|
.is_failed() \
|
|
.has_message(expected_error)
|
|
|
|
|
|
func test_reset():
|
|
var mocked_node = mock(Node)
|
|
|
|
# call with different arguments
|
|
mocked_node.set_process(false) # 1 times
|
|
mocked_node.set_process(true) # 1 times
|
|
mocked_node.set_process(true) # 2 times
|
|
|
|
verify(mocked_node, 2).set_process(true)
|
|
verify(mocked_node, 1).set_process(false)
|
|
|
|
# now reset the mock
|
|
reset(mocked_node)
|
|
# verify all counters have been reset
|
|
verify_no_interactions(mocked_node)
|
|
|
|
|
|
func test_verify_no_interactions():
|
|
var mocked_node = mock(Node)
|
|
|
|
# verify we have no interactions checked this mock
|
|
verify_no_interactions(mocked_node)
|
|
|
|
|
|
func test_verify_no_interactions_fails():
|
|
var mocked_node = mock(Node)
|
|
|
|
# interact
|
|
mocked_node.set_process(false) # 1 times
|
|
mocked_node.set_process(true) # 1 times
|
|
mocked_node.set_process(true) # 2 times
|
|
|
|
var expected_error ="""
|
|
Expecting no more interactions!
|
|
But found interactions on:
|
|
'set_process(false :bool)' 1 time's
|
|
'set_process(true :bool)' 2 time's""" \
|
|
.dedent().trim_prefix("\n")
|
|
# it should fail because we have interactions
|
|
assert_failure(func(): verify_no_interactions(mocked_node)) \
|
|
.is_failed() \
|
|
.has_message(expected_error)
|
|
|
|
|
|
func test_verify_no_more_interactions():
|
|
var mocked_node = mock(Node)
|
|
|
|
mocked_node.is_ancestor_of(null)
|
|
mocked_node.set_process(false)
|
|
mocked_node.set_process(true)
|
|
mocked_node.set_process(true)
|
|
|
|
# verify for called functions
|
|
verify(mocked_node, 1).is_ancestor_of(null)
|
|
verify(mocked_node, 2).set_process(true)
|
|
verify(mocked_node, 1).set_process(false)
|
|
|
|
# There should be no more interactions checked this mock
|
|
verify_no_more_interactions(mocked_node)
|
|
|
|
|
|
func test_verify_no_more_interactions_but_has():
|
|
var mocked_node = mock(Node)
|
|
|
|
mocked_node.is_ancestor_of(null)
|
|
mocked_node.set_process(false)
|
|
mocked_node.set_process(true)
|
|
mocked_node.set_process(true)
|
|
|
|
# now we simulate extra calls that we are not explicit verify
|
|
mocked_node.is_inside_tree()
|
|
mocked_node.is_inside_tree()
|
|
# a function with default agrs
|
|
mocked_node.find_child("mask")
|
|
# same function again with custom agrs
|
|
mocked_node.find_child("mask", false, false)
|
|
|
|
# verify 'all' exclusive the 'extra calls' functions
|
|
verify(mocked_node, 1).is_ancestor_of(null)
|
|
verify(mocked_node, 2).set_process(true)
|
|
verify(mocked_node, 1).set_process(false)
|
|
|
|
# now use 'verify_no_more_interactions' to check we have no more interactions checked this mock
|
|
# but should fail with a collecion of all not validated interactions
|
|
var expected_error ="""
|
|
Expecting no more interactions!
|
|
But found interactions on:
|
|
'is_inside_tree()' 2 time's
|
|
'find_child(mask :String, true :bool, true :bool)' 1 time's
|
|
'find_child(mask :String, false :bool, false :bool)' 1 time's""" \
|
|
.dedent().trim_prefix("\n")
|
|
assert_failure(func(): verify_no_more_interactions(mocked_node)) \
|
|
.is_failed() \
|
|
.has_message(expected_error)
|
|
|
|
|
|
func test_mock_snake_case_named_class_by_resource_path():
|
|
var mock_a = mock("res://addons/gdUnit4/test/mocker/resources/snake_case.gd")
|
|
assert_object(mock_a).is_not_null()
|
|
|
|
mock_a.custom_func()
|
|
verify(mock_a).custom_func()
|
|
verify_no_more_interactions(mock_a)
|
|
|
|
var mock_b = mock("res://addons/gdUnit4/test/mocker/resources/snake_case_class_name.gd")
|
|
assert_object(mock_b).is_not_null()
|
|
|
|
mock_b.custom_func()
|
|
verify(mock_b).custom_func()
|
|
verify_no_more_interactions(mock_b)
|
|
|
|
|
|
func test_mock_snake_case_named_godot_class_by_name():
|
|
# try checked Godot class
|
|
var mocked_tcp_server = mock("TCPServer")
|
|
assert_object(mocked_tcp_server).is_not_null()
|
|
|
|
mocked_tcp_server.is_listening()
|
|
mocked_tcp_server.is_connection_available()
|
|
verify(mocked_tcp_server).is_listening()
|
|
verify(mocked_tcp_server).is_connection_available()
|
|
verify_no_more_interactions(mocked_tcp_server)
|
|
|
|
|
|
func test_mock_snake_case_named_class_by_class():
|
|
var m = mock(snake_case_class_name)
|
|
assert_object(m).is_not_null()
|
|
|
|
m.custom_func()
|
|
verify(m).custom_func()
|
|
verify_no_more_interactions(m)
|
|
|
|
# try checked Godot class
|
|
var mocked_tcp_server = mock(TCPServer)
|
|
assert_object(mocked_tcp_server).is_not_null()
|
|
|
|
mocked_tcp_server.is_listening()
|
|
mocked_tcp_server.is_connection_available()
|
|
verify(mocked_tcp_server).is_listening()
|
|
verify(mocked_tcp_server).is_connection_available()
|
|
verify_no_more_interactions(mocked_tcp_server)
|
|
|
|
|
|
func test_mock_func_with_default_build_in_type():
|
|
var m = mock(ClassWithDefaultBuildIntTypes)
|
|
assert_object(m).is_not_null()
|
|
# call with default arg
|
|
m.foo("abc")
|
|
m.bar("def")
|
|
verify(m).foo("abc", Color.RED)
|
|
verify(m).bar("def", Vector3.FORWARD, AABB())
|
|
verify_no_more_interactions(m)
|
|
|
|
# call with custom color arg
|
|
m.foo("abc", Color.BLUE)
|
|
m.bar("def", Vector3.DOWN, AABB(Vector3.ONE, Vector3.ZERO))
|
|
verify(m).foo("abc", Color.BLUE)
|
|
verify(m).bar("def", Vector3.DOWN, AABB(Vector3.ONE, Vector3.ZERO))
|
|
verify_no_more_interactions(m)
|
|
|
|
|
|
func test_mock_virtual_function_is_not_called_twice() -> void:
|
|
# this test verifies the special handling of virtual functions by Godot
|
|
# virtual functions are handeld in a special way
|
|
# node.cpp
|
|
# case NOTIFICATION_READY: {
|
|
#
|
|
# if (get_script_instance()) {
|
|
#
|
|
# Variant::CallError err;
|
|
# get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_ready,NULL,0);
|
|
# }
|
|
|
|
var m = mock(ClassWithOverridenVirtuals, CALL_REAL_FUNC)
|
|
assert_object(m).is_not_null()
|
|
|
|
# inital constructor
|
|
assert_that(m._x).is_equal("_init")
|
|
|
|
# add_child calls internally by "default" _ready() where is a virtual function
|
|
add_child(m)
|
|
|
|
# verify _ready func is only once called
|
|
assert_that(m._x).is_equal("_ready")
|
|
|
|
# now simulate an input event calls '_input'
|
|
var action = InputEventKey.new()
|
|
action.pressed = false
|
|
action.keycode = KEY_ENTER
|
|
get_tree().root.push_input(action)
|
|
assert_that(m._x).is_equal("ui_accept")
|
|
|
|
|
|
func test_mock_scene_by_path():
|
|
var mocked_scene = mock("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
|
|
assert_object(mocked_scene).is_not_null()
|
|
assert_object(mocked_scene.get_script()).is_not_null()
|
|
assert_str(mocked_scene.get_script().resource_name).is_equal("MockTestScene.gd")
|
|
# check is mocked scene registered for auto freeing
|
|
assert_bool(GdUnitMemoryObserver.is_marked_auto_free(mocked_scene)).is_true()
|
|
|
|
|
|
func test_mock_scene_by_resource():
|
|
var resource := load("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
|
|
var mocked_scene = mock(resource)
|
|
assert_object(mocked_scene).is_not_null()
|
|
assert_object(mocked_scene.get_script()).is_not_null()
|
|
assert_str(mocked_scene.get_script().resource_name).is_equal("MockTestScene.gd")
|
|
# check is mocked scene registered for auto freeing
|
|
assert_bool(GdUnitMemoryObserver.is_marked_auto_free(mocked_scene)).is_true()
|
|
|
|
|
|
func test_mock_scene_by_instance():
|
|
var resource := load("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
|
|
var instance :Control = auto_free(resource.instantiate())
|
|
var mocked_scene = mock(instance)
|
|
# must fail mock an instance is not allowed
|
|
assert_object(mocked_scene).is_null()
|
|
|
|
|
|
func test_mock_scene_by_path_fail_has_no_script_attached():
|
|
var mocked_scene = mock("res://addons/gdUnit4/test/mocker/resources/scenes/TestSceneWithoutScript.tscn")
|
|
assert_object(mocked_scene).is_null()
|
|
|
|
|
|
func test_mock_scene_variables_is_set():
|
|
var mocked_scene = mock("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
|
|
assert_object(mocked_scene).is_not_null()
|
|
|
|
# Add as child to a node to trigger _ready to initalize all variables
|
|
add_child(mocked_scene)
|
|
assert_object(mocked_scene._box1).is_not_null()
|
|
assert_object(mocked_scene._box2).is_not_null()
|
|
assert_object(mocked_scene._box3).is_not_null()
|
|
|
|
# check signals are connected
|
|
assert_bool(mocked_scene.is_connected("panel_color_change", Callable(mocked_scene, "_on_panel_color_changed")))
|
|
|
|
# check exports
|
|
assert_str(mocked_scene._initial_color.to_html()).is_equal(Color.RED.to_html())
|
|
|
|
|
|
func test_mock_scene_execute_func_yielded() -> void:
|
|
var mocked_scene = mock("res://addons/gdUnit4/test/mocker/resources/scenes/TestScene.tscn")
|
|
assert_object(mocked_scene).is_not_null()
|
|
add_child(mocked_scene)
|
|
# execute the 'color_cycle' func where emits three signals
|
|
# using yield to wait for function is completed
|
|
var result = await mocked_scene.color_cycle()
|
|
# verify the return value of 'color_cycle'
|
|
assert_str(result).is_equal("black")
|
|
|
|
verify(mocked_scene)._on_panel_color_changed(mocked_scene._box1, Color.RED)
|
|
verify(mocked_scene)._on_panel_color_changed(mocked_scene._box1, Color.BLUE)
|
|
verify(mocked_scene)._on_panel_color_changed(mocked_scene._box1, Color.GREEN)
|
|
|
|
|
|
class Base:
|
|
func _init(_value :String):
|
|
pass
|
|
|
|
|
|
class Foo extends Base:
|
|
func _init():
|
|
super("test")
|
|
pass
|
|
|
|
|
|
func test_mock_with_inheritance_method() -> void:
|
|
var foo = mock(Foo)
|
|
assert_object(foo).is_not_null()
|