При модульном тестировании класса, который действует как интерфейс между вашим приложением и сторонним API (даже системным API), вы хотите проверить, что класс вызывает и правильно отвечает на API.Вы не можете сделать это без какого-либо способа определить, что передается в API, и вернуть соответствующий ответ.
В вашем случае вы делаете серию вызовов для получения IAudioClient.Я бы сказал, что ты слишком много делаешь.Более одного условия в функции - это одно условие слишком много (я думаю, что я просто перепутал себя с этим).Я бы разбил его на несколько функций, которые вы можете протестировать по отдельности.
function TCoreAudio.CreateAudioClient: IAudioClient;
var
MMDeviceEnumerator: IMMDeviceEnumerator;
MMDevice: IMMDevice;
MixFormat: PWaveFormatEx;
AudioClient: IAudioClient;
begin
Result := nil;
if IsVista then
try
MMDeviceEnumerator := GetMMDeviceEumerator;
MMDevice := GetMMDevice(MMDeviceEnumerator);
AudioClient := GetAudioClient(MMDevice);
MixFormat := GetMixFormat(AudioClient);
InitializeAudioClient(AudioClient, MixFormat);
Result := AudioClient;
except
//Handle exception
end;
end;
function TCoreAudio.IsVista: boolean;
begin
Result := CheckWin32Version(6, 0);
end;
function TCoreAudio.GetMMDeviceEnumerator: IMMDeviceEnumerator;
begin
HR := GetInstance().CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL,
IMMDeviceEnumerator, Result);
if Failed(HR) then
raise Exception.Create('Failed to create device enumerator');
end;
function TCoreAudio.GetMMDevice(ADeviceEnumerator: IMMDeviceEnumerator): IMMDevice;
begin
HR := MMDeviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, Result);
if Failed(HR) then
raise Exception.Create('Failed to retrieve device');
end;
function TCoreAudio.GetAudioClient(ADevice: IMMDevice): IAudioClient;
begin
HR := MMDevice.Activate(IAudioClient, CLSCTX_ALL, nil, Result);
if Failed(HR) then
raise Exception.Create('Failed to retrieve audio client');
end;
function TCoreAudio.GetMixFormat(AAudioClient: IAudioClient): PWaveFormatEx
begin
HR := AudioClient.GetMixFormat(Result);
if Failed(HR) then
raise Exception.Create('Failed to retrieve mix format');
end;
procedure TCoreAudio.InitializeAudioClient(AAudioClient: IAudioClient, AMixFormat: PWaveFormatEx);
begin
HR := AudioClient.Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, AMixFormat, nil);
CoTaskMemFree(MixFormat);
if Failed(HR) then
raise Exception.Create('Audio client failed to initialize');
end;
Теперь вы можете предоставить макет / фальшивку / заглушку для каждой функции, гарантируя, что API вызывается с соответствующими аргументами, и заставляя условия сбояубедитесь, что ваш производственный код обрабатывает их правильно.
Вам не нужно спрашивать, должен ли производственный код проверяться.Ответ всегда да.(предупреждение: бесстыдная самореклама) Я недавно писал об этом в своем блоге .Иногда даже самый безобидный из всех операторов, оператор присваивания, работает не так, как ожидалось.
На самом деле теперь, когда он разбит, он начинает выглядеть как новый творческий класс, просто жаждущий вырваться.