I'm working on a simple tool that imports a set of fbx models to be resized on Blender. The first model is the source that the rest of models will be resized to. The first part of the algorithm is to import the models and rename them, that's done and tested. However, I struggle to find a way to mock bpy.ops.export_scene.fbx to avoid creating new files.
My problem with this mock is that in spite of being created with patch as I could check with a print statement in Python REPL, the mock doesn't work when I perform my test with pytest. This is the summary of the test output:
FAILED test_blender_resizer.py::TestModelExport::test_file_export - RuntimeError: Error: Python: Traceback (most recent call last):
File "C:\Program Files\Blender Foundation\Blender 4.3\4.3\scripts\addons_core\io_scene_fbx\__init__.py", line 596, in execute
return export_fbx_bin.save(self, context, **keywords)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Blender Foundation\Blender 4.3\4.3\scripts\addons_core\io_scene_fbx\export_fbx_bin.py", line 3657, in save
ret = save_single(operator, context.scene, depsgraph, filepath, **kwargs_mod)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Blender Foundation\Blender 4.3\4.3\scripts\addons_core\io_scene_fbx\export_fbx_bin.py", line 3538, in save_single
encode_bin.write(filepath, root, FBX_VERSION)
File "C:\Program Files\Blender Foundation\Blender 4.3\4.3\scripts\addons_core\io_scene_fbx\encode_bin.py", line 402, in write
with open(fn, 'wb') as f:
^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\juank\\dev\\game_tools\\grin_gate_studios\\art\\resizer\\blender_scripts\\tests\\output\\target_one.fbx'
Location: C:\Program Files\Blender Foundation\Blender 4.3\4.3\scripts\modules\bpy\ops.py:109
I've got two questions here:
- Is there a special way to mock Blender Python API:
My test
def setUp(self):
self.dir = os.path.dirname(__file__)
self.c = len(bpy.data.objects)
self.o = bpy.data.objects
@patch("bpy.ops.export_scene.fbx")
def test_file_export(self, mock_fbx):
t = os.path.join(self.dir, "dummies", "target_one.fbx")
blender_resizer.import_model(os.path.join(self.dir, "dummies/source.fbx"))
blender_resizer.import_model(os.path.join(self.dir, t))
blender_resizer.export_resized_meshes(
os.path.join(self.dir, "output", "target_one.fbx")
)
assert mock_fbx.assert_called_once_with(t)
My code:
def export_resized_meshes(output: str):
o = bpy.data.objects
m = [obj for obj in bpy.data.objects if obj.type == "MESH" and not obj.parent]
for i in range(1, len(m)):
m[i].dimensions = m[1].dimensions
m[i].select_set(True)
bpy.ops.export_scene.fbx(
filepath=output, use_selection=True, check_existing=False
)
m[i].select_set(False)
- Why Blender complains about a non-existing file? Does it create a new when it exports the model? I guess this is the case but to me it is weird to see that it needs an existing file as though it would overwrite it on export.
outputfolder was not created. However, I'd still like to know how to mockbpy.ops.export_scene.fbx$\endgroup$