You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python单元测试:如何Mock传入函数的OpenZWave Network类对象?

Let's walk through exactly how to isolate and test your get_temperature function without needing a real Z-Wave network or sensors. The key is correctly mocking the nested OpenZWave objects—your earlier attempts with Mock/MagicMock likely failed because you didn't fully replicate the nested property chain (network → nodes → multisensor → values). Here's a step-by-step solution using Python's standard libraries, plus optional tools to simplify things.

Step 1: Break Down the Dependency Chain

First, let's map out what your function actually needs from the network_obj:

  1. network_obj.nodes[sensor_id]: A multisensor object
  2. multisensor.get_values(): A method call (no return value needed, just needs to be callable)
  3. multisensor.values: A dictionary of value objects, each with a label and data attribute

We can mock each of these layers explicitly to control exactly what data is returned.

Step 2: Explicit Mocking (Simplest for Your Case)

Instead of using patch right away, let's build mock objects from the bottom up. This makes it easy to see exactly what's being simulated.

Here's a complete test case using unittest and unittest.mock:

import unittest
from unittest.mock import Mock, MagicMock
from your_module import get_temperature  # Replace with your actual module name

class TestGetTemperature(unittest.TestCase):
    def test_extracts_correct_temperature(self):
        # 1. Mock the individual temperature value object
        temp_value = Mock()
        temp_value.label = "Temperature"
        temp_value.data = 25.5  # Sample temperature reading

        # 2. Mock other sensor values (to simulate a real multisensor)
        humidity_value = Mock()
        humidity_value.label = "Humidity"
        humidity_value.data = 62

        # 3. Mock the multisensor itself
        multisensor = Mock()
        multisensor.values = {
            "temp_key": temp_value,
            "humidity_key": humidity_value
        }
        multisensor.get_values = MagicMock()  # Mock the method call

        # 4. Mock the network object
        network_obj = Mock()
        network_obj.nodes = {"sensor_123": multisensor}  # Match your test sensor ID

        # 5. Run the function under test
        result = get_temperature("sensor_123", network_obj)

        # 6. Verify results and method calls
        self.assertEqual(result, {"Temperature": 25.5})
        multisensor.get_values.assert_called_once()  # Ensure get_values() was triggered

    def test_handles_missing_sensor_id(self):
        # Test what happens when the sensor ID doesn't exist
        network_obj = Mock()
        network_obj.nodes = {}

        with self.assertRaises(KeyError):
            get_temperature("invalid_sensor", network_obj)

    def test_handles_no_temperature_value(self):
        # Test when the sensor has no temperature reading
        multisensor = Mock()
        multisensor.values = {}
        multisensor.get_values = MagicMock()

        network_obj = Mock()
        network_obj.nodes = {"sensor_123": multisensor}

        result = get_temperature("sensor_123", network_obj)
        self.assertEqual(result, {})

Step 3: Using patch for Class-Level Mocking

If your function is creating or importing an OpenZWave Network class directly, you can use @patch to replace the entire class with a mock. Here's how that would look:

from unittest.mock import patch

class TestGetTemperatureWithPatch(unittest.TestCase):
    @patch("your_module.Network")  # Replace with where Network is imported from
    def test_with_patch(self, mock_network_class):
        # Get the mock network instance
        mock_network = mock_network_class.return_value

        # Build the same mock multisensor as before
        temp_value = Mock()
        temp_value.label = "Temperature"
        temp_value.data = 22.0

        multisensor = Mock()
        multisensor.values = {"temp": temp_value}
        multisensor.get_values = MagicMock()

        # Attach the multisensor to the mock network's nodes
        mock_network.nodes = {"sensor_456": multisensor}

        # Run the test
        result = get_temperature("sensor_456", mock_network)
        self.assertEqual(result, {"Temperature": 22.0})
  • Python's built-in unittest.mock: This is all you need for basic mocking—it's part of the standard library, so no extra installs required.
  • pytest + pytest-mock: If you prefer pytest over unittest, the pytest-mock plugin provides a mocker fixture that simplifies mock setup (no need to import Mock/MagicMock directly). Example:
    def test_with_pytest_mock(mocker):
        temp_value = mocker.Mock(label="Temperature", data=24.0)
        multisensor = mocker.Mock(
            values={"temp_key": temp_value},
            get_values=mocker.MagicMock()
        )
        network_obj = mocker.Mock(nodes={"sensor_789": multisensor})
    
        result = get_temperature("sensor_789", network_obj)
        assert result == {"Temperature": 24.0}
    

Key Takeaways

  • Always mock the entire dependency chain: Don't skip layers (e.g., don't mock just network_obj without setting up its nodes attribute).
  • Use MagicMock for methods you need to verify were called (like get_values()).
  • Test edge cases: Missing sensors, missing temperature values, etc.—this makes your tests more robust.

内容的提问来源于stack exchange,提问作者Gubimand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:33:12