Nel namespace Microsoft.VisualStudio.TestTools.UnitTesting
, è disponibile la comoda classe statica Assert
per gestire le asserzioni in corso nei test.Microsoft.VisualStudio.TestTools.UnitTesting.Assert comportamento generico di overload dei metodi
Qualcosa che mi ha infastidito è che la maggior parte dei metodi sono estremamente sovraccarichi e, per di più, hanno una versione generica. Un esempio specifico è Assert.AreEqual
che ha 18 sovraccarichi, tra i quali:
Assert.AreEqual<T>(T t1, T t2)
Qual è l'uso di questo metodo generico? Inizialmente, pensavo che fosse un modo per chiamare direttamente il metodo IEquatable<T> Equals(T t)
, ma non è questo il caso; chiamerà sempre la versione non generica object.Equals(object other)
. Ho scoperto la via difficile dopo aver codificato alcuni test unitari in attesa di tale comportamento (invece di esaminare in anticipo la definizione della classe Assert
come avrei dovuto).
Al fine di chiamare la versione generica del Equals
, il metodo generico avrebbe dovuto essere definito come:
Assert.AreEqual<T>(T t1, T t2) where T: IEquatable<T>
C'è un buon motivo per cui non è stato fatto in questo modo?
Sì, si perde il metodo generico per tutti quei tipi che non implementano IEquatable<T>
, ma non è una grande perdita comunque come l'uguaglianza sarebbe visibile attraverso object.Equals(object other)
, quindi Assert.AreEqual(object o1, object o2)
è già abbastanza buono.
L'attuale metodo generico offre vantaggi che non sto considerando, o è solo il caso che nessuno si è fermato a pensarci perché non è un granché? L'unico vantaggio che vedo è la sicurezza del tipo di argomento, ma sembra piuttosto scadente.
Edit: fissato un errore in cui ho continuato riferendosi al IComparable
quando volevo dire IEquatable
.
Non è possibile vincolarlo, poiché qualsiasi T senza il proprio sovraccarico si risolverebbe naturalmente a tale metodo come parte della risoluzione di sovraccarico e solo allora il compilatore si lamenterà del vincolo non soddisfatto per qualsiasi T che non implementa l'interfaccia. Per quanto riguarda l'ipotesi errata, hai controllato la documentazione del metodo prima di costruire la strategia di test intorno ad essa? –
AnthonyPegram: se lo si limita non si può passare in nessuna T che non implementa l'interfaccia, quindi come esattamente la risoluzione di sovraccarico si guasterebbe in runtime? – InBetween
Fallirebbe al momento della compilazione, ma la risoluzione del sovraccarico avrebbe già deciso sull'overload T e * quindi * controllare il vincolo (e fallire). I vincoli non fanno parte della firma. Se cerchi questa frase, troverai molte risorse (qui e altrove, in particolare il blog di Eric Lippert) che ti forniranno maggiori dettagli al riguardo. –