Estoy tratando de escribir algunas pruebas unitarias. La aplicación tiene una serie de llamadas API externas que me gustaría simular usando NSubstitute. El problema es que estas llamadas usan objetos de servicio que deben instanciarse en la función y no se pueden pasar en el constructor después de la sustitución.
Por ejemplo, en el siguiente código estoy agregando una cuenta a Quickbooks:
public async Task AddQuickbooksAsync(int accountId) { var qbChannel = await GetQuickbooksChannel(); var account = await GetAsync(accountId); var quickbooksBO = new QuickbooksBO(qbChannel); quickbooksBO.AddAccount(account); quickbooksBO.UpdateRefreshedTokens(qbChannel); await context.SaveChangesAsync(); }Quiero simular la siguiente llamada de función usando NSubstitute, pero no pude averiguar cómo:
var quickbooksBO = new QuickbooksBO(qbChannel); quickbooksBO.AddAccount(account);¿Cómo puedo hacer esto?
No puedes burlarte de una variable local. Puede crear un método virtual que devolverá QuickbooksBO y lo sustituirá.
public async Task AddQuickbooksAsync(int accountId) { var qbChannel = await GetQuickbooksChannel(); var account = await GetAsync(accountId); var quickbooksBO = GetQbBO(qbChannel); quickbooksBO.AddAccount(account); quickbooksBO.UpdateRefreshedTokens(qbChannel); await context.SaveChangesAsync(); } public virtual QuickbooksBO GetQbBO(Channel qbChannel) { return new QuickBooks(qbChannel); }Después de eso, puede sustituirlo en su servicio:
var s = Substitute.ForPartsOf<Service>(); s.GetQbBO(default).ReturnsForAnyArgs(substituteForQbBO);Deberá averiguar qué partes de QuickBooksBO desea simular. Por lo general, tales dependencias deberían ser interfaces, sin interfaces, las pruebas unitarias son bastante limitadas.
Si los métodos de QuickbooksBO son virtuales, puede hacer algo como esto para obtener su substituteForQbBO :
var substituteForQbBO = Substitute.ForPartsOf<QuickbooksBO>(); substituteForQbBO.WhenForAnyArgs(x => x.AddAccount(default)).DoNotCallBase(); substituteForQbBO.WhenForAnyArgs(x => x.UpdateRefreshedTokens(default)).DoNotCallBase();