Tenho um método CancelScheduledJob que recebe o Id de um trabalho em segundo plano e usa o JobStorage para recuperar esse Id e cancelar o trabalho hangfire correspondente:
var mon = JobStorage.Current.GetMonitoringApi();
var scheduledJobs = mon.ScheduledJobs(0, int.MaxValue);
var jobsToDelete = scheduledJobs.Where(job => job.Value.Job?.Args?.Any(arg => arg is Guid guid && guid == id) == true).ToList();
jobsToDelete?.ForEach(job => _backgroundJobClient.Delete(job.Key));
É possível verificar um método Enqueue() ou Schedule() verificando o método Create chamado no mock backgroundJobClient, como aqui:
_backgroundJobClientMock.Verify(x => x.Create(
It.Is<Job>(job => job.Method.Name == "Run" && Guid.Parse(job.Args[0].ToString()) == input),
It.IsAny<ScheduledState>()));
Mas como eu faria para verificar o método Delete? Já estou zombando do JobStorage, mas não consigo encontrar uma maneira de verificar o método Delete(). Atualmente, tenho isto:
_backgroundJobClientMock.Verify(
x => x.Delete(It.Is<string>(jobId => jobId == "job1")),
Times.Once
);
Mas me deparo com o problema comum de que Delete é um método de extensão e não pode ser usado em uma expressão de configuração/verificação.
Você pode fazer algo "esquisito" e testar o método de instância que é chamado pelo método de extensão - ( código-fonte atual ):
Isso seria
ChangeState
, portanto,Verify
contra isso.EDITAR :
Se você não puder ou (não quiser) encapsular coisas em uma interface personalizada em seu código real como as outras respostas sugerem, você pode verificar esta minha resposta para uma abordagem alternativa. Era para verificar
ILogger
métodos de extensão s comoLogInformation
, mas deve funcionar aqui também se você estiver dependendo deIBackgroundJobClient
. Em poucas palavras, você cria umaIBackgroundJobClientExt:IBackgroundJobClient
interface que inclui os métodos de extensão explicitamente. Então useDispatchProxy
para criar uma instância dela e passá-la para nossosut
. Dessa forma, você ainda pode usarVerify
contraDelete
em seu código de teste e manter a conexão entre métodos de extensão e métodos de instância que eles chamam em um único lugar - no métodoDispatchProxy
'sInvoke
.Como Ivan Petrov escreve, você pode testar um método de extensão quando sabe como ele é implementado. Isso permite que você verifique em relação à API subjacente que o método de extensão usa.
No entanto, isso leva a testes frágeis. Seus testes agora estão vulneráveis a alterações em uma biblioteca de terceiros.
Uma opção melhor é definir uma API polimórfica (interface ou classe base) que seja definida com base nas necessidades do seu código cliente, em vez de detalhes de implementação. Aqui, consideramos toda a Hangfire API um detalhe de implementação.
Isso seguiria mais apropriadamente o Princípio de Inversão de Dependência . Você define a abstração contra a qual está programando com base no que seu código cliente precisa, em vez do que alguma API de terceiros oferece.
Depois de definir a API necessária , implemente a interface ou classe base com os detalhes de implementação: a API Hangfire.
Para complementar as respostas existentes, especialmente a resposta de Mark, você deve definir a interface em torno
_backgroundJobClient
do tipo '.Algo como:
Então você pode facilmente simular
IBackgroundJobClientWrapper
a interface.É claro que você pode ajustar a definição da interface para melhor se adequar ao seu código.