Depuis que j'ai converti mes méthodes WCF en Async, mes tests unitaires ont échoué et je ne peux pas trouver la syntaxe correcte pour les faire fonctionner.
classe proxy Cllient
public interface IClientProxy
{
Task DoSomething(CredentialDataList credentialData, string store);
}
classe de service
public class CredentialSync : ICredentialSync
{
private ICredentialRepository _repository;
private IClientProxy _client;
public CredentialSync()
{
this._repository = new CredentialRepository();
this._client = new ClientProxy();
}
public CredentialSync(ICredentialRepository repository, IClientProxy client)
{
this._repository = repository;
this._client = client;
}
public async Task Synchronise(string payrollNumber)
{
try
{
if (string.IsNullOrEmpty(payrollNumber))
{
.... some code
}
else
{
CredentialDataList credentialData = new CredentialDataList();
List<CredentialData> credentialList = new List<CredentialData>();
// fetch the record from the database
List<GetCredentialData_Result> data = this._repository.GetCredentialData(payrollNumber);
var pinData = this._repository.GetCredentialPinData(payrollNumber);
// get the stores for this employee
var storeList = data.Where(a => a.StoreNumber != null)
.GroupBy(a => a.StoreNumber)
.Select(x => new Store { StoreNumber = x.Key.ToString() }).ToArray();
var credential = this.ExtractCredentialData(data, pinData, payrollNumber);
credentialList.Add(credential);
credentialData.CredentialList = credentialList;
foreach (var store in storeList)
{
//this line causes an Object reference not set to an instance of an object error
await _client.DoSomething(credentialData, store.StoreNumber);
}
}
}
catch (Exception ex)
{
throw new FaultException<Exception>(ex);
}
}
Classe de test
/// </summary>
[TestClass]
public class SynchTest
{
private Mock<ICredentialRepository> _mockRepository;
private Mock<IClientProxy> _mockService;
[TestInitialize]
public void Setup()
{
... some setups for repository which work fine
}
[TestMethod]
public async Task SynchroniseData_WithOneEmployee_CallsReplicateService()
{
this._mockService = new Mock<IClientProxy>();
this._mockService.Setup(x=>x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()));
// arrange
string payrollNumber = "1";
CredentialSync service = new CredentialSync(this._mockRepository.Object, this._mockService.Object);
// act
await service.Synchronise(payrollNumber);
// assert
this._mockService.VerifyAll();
}
L'erreur est lorsque ClientProxy.DoSomething
Est appelé:
La référence d'objet n'est pas définie à une instance d'un objet
Les paramètres sont tous les deux très bien.
Si je convertis ma méthode ClientProxy.DoSomething
En une méthode synchrone (public void DoSomething(...)
) le code fonctionne bien, mais j'ai besoin que cela soit appelé de manière asynchrone
DoSomething
renvoie null
au lieu de renvoyer un Task
, et vous obtenez donc une exception en l'attendant. Vous devez spécifier lors de la construction de la maquette qu'elle doit renvoyer un Task
.
Dans ce cas, il semble que vous pouvez simplement retourner une tâche déjà terminée en utilisant Task.FromResult
donc la configuration simulée devrait ressembler à ceci:
this._mockService.Setup(...).Returns(Task.FromResult(false));
À partir de la prochaine version de .Net (4.6), vous pouvez utiliser Task.CompletedTask
comme ça:
this._mockService.Setup(...).Returns(Task.CompletedTask);
Vous pouvez réduire l'encombrement dans le code à l'aide de ReturnsAsync
this._mockService.Setup(...).ReturnsAsync(false)
;
De cette façon, vous pouvez supprimer le Task.FromResult
partie du code
Je pense que vous devez renvoyer le Task
du DoSomething
mock
this._mockService.Setup(x => x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()))
.Returns(Task.FromResult<int>(0));