towerops/test/towerops/workers/discovery_worker_test.exs
Graham McIntire b116ed4f71
Fix worker test mock expectations and API calls
- Fix Monitoring context API calls (list_devices_checks vs list_checks_for_device)
- Fix Snmp context API calls (get_interface_stats, get_sensor_readings)
- Fix Devices context API calls (update_device vs update_device!)
- Fix Discovery worker to expect 7 GET calls (test_connection + system_info)
- Fix Poll worker to use stub instead of expect for variable call counts
- Fix sensor setup to use correct types (sensor_index: string, sensor_divisor: integer)
- Fix neighbor schema to include required fields (protocol, last_discovered_at)
- Simplify walk mocks to use stub for complex neighbor discovery

18 of 23 tests now passing. Remaining issues:
- 1 sensor error reading test (may need investigation)
- 4 log capture tests (ExUnit.CaptureLog not capturing logs from workers)
2026-01-20 12:13:14 -06:00

125 lines
4 KiB
Elixir

defmodule Towerops.Workers.DiscoveryWorkerTest do
use Towerops.DataCase, async: true
import Mox
import Towerops.AccountsFixtures
alias Towerops.Snmp
alias Towerops.Snmp.SnmpMock
alias Towerops.Workers.DiscoveryWorker
setup :verify_on_exit!
describe "perform/1" do
setup do
user = user_fixture()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
{:ok, site} =
Towerops.Sites.create_site(%{
name: "Test Site",
organization_id: organization.id
})
{:ok, device} =
Towerops.Devices.create_device(%{
name: "Test Device",
ip_address: "192.168.1.1",
snmp_enabled: true,
snmp_version: "2c",
snmp_community: "public",
snmp_port: 161,
site_id: site.id
})
{:ok, device: device, org: organization}
end
test "successfully discovers a device", %{device: device} do
# Mock SNMP responses for discovery (test_connection + system_info = 7 calls)
expect(SnmpMock, :get, 7, fn _target, oid, _opts ->
case oid do
"1.3.6.1.2.1.1.1.0" -> {:ok, "Test Device"}
"1.3.6.1.2.1.1.2.0" -> {:ok, [1, 3, 6, 1, 4, 1, 9]}
# sysUpTime (also used by test_connection)
"1.3.6.1.2.1.1.3.0" -> {:ok, 12_345}
"1.3.6.1.2.1.1.4.0" -> {:ok, "admin@test.com"}
"1.3.6.1.2.1.1.5.0" -> {:ok, "test-device"}
"1.3.6.1.2.1.1.6.0" -> {:ok, "Test Location"}
end
end)
# Mock interface discovery (if_index walk + other IF-MIB walks) and neighbor discovery
# Total: if_index + if_descr + if_type + if_speed + if_phys_address + if_admin_status +
# if_oper_status + if_name + if_alias (9 walks) + LLDP (6 walks) + CDP (1 walk) = 16 walks
# Simplify: just allow any number of walk calls to return empty
stub(SnmpMock, :walk, fn _target, _oid, _opts ->
{:ok, []}
end)
assert :ok = DiscoveryWorker.perform(device.id)
# Verify SNMP device was created
snmp_device = Snmp.get_device(device.id)
assert snmp_device
assert snmp_device.sys_descr == "Test Device"
assert snmp_device.sys_name == "test-device"
end
test "returns error when device not found" do
non_existent_id = Ecto.UUID.generate()
assert {:error, :device_not_found} = DiscoveryWorker.perform(non_existent_id)
end
test "returns error when discovery fails", %{device: device} do
# Mock SNMP failure (test_connection fails immediately)
expect(SnmpMock, :get, fn _target, _oid, _opts ->
{:error, :timeout}
end)
assert {:error, _reason} = DiscoveryWorker.perform(device.id)
end
test "logs appropriate messages", %{device: device} do
import ExUnit.CaptureLog
# Mock SNMP responses (test_connection + system_info = 7 calls)
expect(SnmpMock, :get, 7, fn _target, oid, _opts ->
case oid do
"1.3.6.1.2.1.1.1.0" -> {:ok, "Test"}
"1.3.6.1.2.1.1.2.0" -> {:ok, [1, 3, 6, 1]}
"1.3.6.1.2.1.1.3.0" -> {:ok, 1}
"1.3.6.1.2.1.1.4.0" -> {:ok, ""}
"1.3.6.1.2.1.1.5.0" -> {:ok, "test"}
"1.3.6.1.2.1.1.6.0" -> {:ok, ""}
end
end)
# Allow any number of walk calls (interface + neighbor discovery)
stub(SnmpMock, :walk, fn _target, _oid, _opts -> {:ok, []} end)
log =
capture_log([level: :info], fn ->
DiscoveryWorker.perform(device.id)
end)
assert log =~ "Starting SNMP discovery for device #{device.id}"
assert log =~ "SNMP discovery completed successfully for device #{device.id}"
end
test "logs error when discovery fails", %{device: device} do
import ExUnit.CaptureLog
expect(SnmpMock, :get, fn _target, _oid, _opts ->
{:error, :network_unreachable}
end)
log =
capture_log(fn ->
DiscoveryWorker.perform(device.id)
end)
assert log =~ "SNMP discovery failed for device #{device.id}"
end
end
end