2017-08-18 1 views
1

Je suis nouveau sur XUnit et Moq. J'essaie de comprendre à la fois les cadres de test et la préparation des cas de tests unitaires. J'utilise l'injection de dépendance pour injecter les interfaces.Utilisation de Moq et Xunit pour tester les interfaces

Je teste les interfaces suivantes

using System.Collections.Generic; 
using Zeiss.IMT.MCCNeo.Settings.Entities; 

namespace Zeiss.IMT.MCCNeo.Settings.Data.Interface 
{ 
    public interface IProfilesRepository 
    { 
     IList<Profile> GetAllProfiles(); 
     IList<Profile> GetProfilesMatchingUserID(string userid); 
     IList<Profile> GetProfilesForUserIDWithSettingName(string userid, string settingname); 
    } 
} 

La classe d'implémentation

using System; 
using System.Collections.Generic; 
using Zeiss.IMT.MCCNeo.Settings.Data.Interface; 
using Zeiss.IMT.MCCNeo.Settings.Entities; 
using System.Linq; 
using Zeiss.IMT.MCCNeo.Settings.Data.Singleton; 
using Zeiss.IMT.MCCNeo.Settings.Utilities; 

namespace Zeiss.IMT.MCCNeo.Settings.Data.Repository 
{ 
    public class ProfilesRepository : IProfilesRepository 
    { 
     private IProfileDataRepository _profileDataRepository { get; set; } 
     public ProfilesRepository(IProfileDataRepository ProfileDataRepository) 
     { 
      _profileDataRepository = ProfileDataRepository; 

     } 
     public IList<Profile> GetAllProfiles() 
     { 
      return _profileDataRepository.Get(); 
     } 
     public IList<Profile> GetProfilesMatchingUserID(string userid) 
     { 
      if (string.IsNullOrWhiteSpace(userid)) throw new ArgumentException("User Id Cannot be null"); 
      return _profileDataRepository.Get().Where(puid => puid.UserID.ToLower() == userid.ToLower()).ToList<Profile>(); 
     } 
     public IList<Profile> GetProfilesForUserIDWithSettingName(string userid, string settingname) 
     { 
      if (string.IsNullOrWhiteSpace(userid) || string.IsNullOrWhiteSpace(settingname)) throw new ArgumentException("User Id or settingname Cannot be null"); 
      var profilesWithSettings = _profileDataRepository.Get().Where(p => p.UserID.ToLower() == userid.ToLower() & p.Settings.Any(s => s.Name.ToLower() == settingname.ToLower())); 
      return profilesWithSettings.ToList(); 
     } 
    } 
} 

Le référentiel de données qui traite des données de chargement et de la sauvegarde des données dans un fichier

using System; 
using System.Collections.Generic; 
using Zeiss.IMT.MCCNeo.Settings.Entities; 

namespace Zeiss.IMT.MCCNeo.Settings.Data.Singleton 
{ 
    public interface IProfileDataRepository 
    { 
     List<Profile> Get(); 

     List<Profile> Get(Func<Profile, bool> filter); 
     void Save(List<Profile> profilesToSave); 
    } 
} 

using System; 
using System.Collections.Generic; 
using Zeiss.IMT.MCCNeo.Settings.Entities; 
using Zeiss.IMT.MCCNeo.Settings.Utilities; 
using System.Linq; 
namespace Zeiss.IMT.MCCNeo.Settings.Data.Singleton 
{ 
    public class ProfileDataRepository : IProfileDataRepository 
    { 
     private static List<Profile> profiles; 
     public IRepository _repository { get; set; } 
     public ProfileDataRepository(IRepository repository) 
     { 
      _repository = repository; 
      if (profiles == null) 
      { 
       profiles = repository.Get<Profile>(); 
      } 
     } 

     public List<Profile> Get() 
     { 
      return profiles; 
     } 

     public List<Profile> Get(Func<Profile, bool> filter) 
     { 
      return profiles.Where(filter).ToList(); 
     } 

     public void Save(List<Profile> profilesToSave) 
     { 
      profiles = profilesToSave; 
      _repository.Save<List<Profile>>(profiles); 
     } 
    } 
} 

Je suis essayer de se moquer de l'entité Profile puis de la passer aux interfaces simulées. Mais, je manque encore de compréhension sur la façon de se moquer des interfaces et de transmettre les entités de données.

Entity class 

    namespace Zeiss.IMT.MCCNeo.Settings.Entities 
    { 
     public class Profile 
     { 
      public string UserID { get; set; } 
      public string UserName { get; set; } 
      public List<Setting> Settings { get; set; } 
     } 
    } 

Test class 

    using Moq; 
using System; 
using System.Collections.Generic; 
using System.Text; 
using Zeiss.IMT.MCCNeo.Settings.Data.Interface; 
using Zeiss.IMT.MCCNeo.Settings.Data.Singleton; 
using Zeiss.IMT.MCCNeo.Settings.Entities; 

namespace Zeiss.IMT.MCCNeo.Settings.Tests 
{ 
    public class ProfilesServiceTests 
    { 
     private readonly Mock<IProfileDataRepository> ProfileDataProvider; 
     private readonly Mock<IProfilesRepository> ProfilesProvider; 

     public ProfilesServiceTests() 
     { 
      ProfileDataProvider = new Mock<IProfileDataRepository>(); 
      ProfilesProvider = new Mock<IProfilesRepository>(); 
     } 

     public void GetProfilesMatchingUserID_WhenPassedNull_Return_Exception() 
     { 

      List<Setting> settings = new List<Setting>() { 
       new Setting(){ 
        Name = "RefreshInterval", 
        Value = { }, 
        Type = "string", 
       Encrypted = true, 
       ReadOnly = true, 
       CreatedOn = new DateTime(), 
       ModifiedOn = new DateTime(), 
       Valid = true, 
       Enabled = true, 
       Description = "Protocol Archive view renwal interval in seconds. Minimum value = 300 Maximum value = 28800" 
       } 
      }; 

      Profile profile = new Profile() 
      { 
       UserID = "admin", 
       UserName = "admin", 
       Settings = settings 
      }; 

      List<Profile> profiles = new List<Profile>() 
      { 
       profile 
      }; 

      ProfileDataProvider.Setup(x => x.Get()).Returns(profiles); 
      ProfilesProvider.Setup(x => x.GetProfilesMatchingUserID(null)).Returns(new NullReferenceException()); 

     } 
    } 
} 

Bien vouloir suggérer.

+1

Quelle est exactement votre question? –

Répondre

2

Il semble que vous vouliez tout tester (ou beaucoup) dans une classe. Gardez à l'esprit que vous n'avez pas besoin de faire des tests d'intégration (pour l'instant).

Regardez d'abord votre ProfilesRepository.

Nous avons besoin de quelque chose comme

public class ProfileRepositoryTests 
{ 
    //this class is only reposible to handle data from the IProfileDataRepository 
    private readonly ProfilesRepository _profilesRepository; 
    private readonly Mock<IProfileDataRepository> _moqProfileDataProvider; 

    public ProfileRepositoryTests() 
    { 
     _moqProfileDataProvider = new Mock<IProfileDataRepository>(); 
     _profilesRepository = new ProfilesRepository(_moqProfileDataProvider.Object); 
    } 

    [Fact] 
    public void Get_Succes_NoProfiles() 
    { 
     _moqProfileDataProvider.Setup(x => x.Get()).Returns(new List<Profile>()); 

     var profiles = _profilesRepository.GetAllProfiles(); 

     Assert.AreEqual(0, profiles.Count); 
    } 

    [Fact] 
    public void Get_Succes_AllProfiles() 
    { 
     _moqProfileDataProvider.Setup(x => x.Get()).Returns(new List<Profile> 
     { 
      new Profile {UserID = "123"} 
     }); 

     var profiles = _profilesRepository.GetAllProfiles(); 

     Assert.AreEqual(1, profiles.Count); 
     Assert.AreEqual("123", profiles.First().UserID); 
     //test more properties 
    } 

    [Fact] 
    public void GetProfilesMatchingUserID_userId_null_Throws_Error() 
    { 
     Exception ex = Assert.Throws<ArgumentException>(() => _profilesRepository.GetProfilesMatchingUserID(null));  
    } 
} 

Cela ne termine pas tous les tests, mais vous donne une idée comment vous pouvez continuer. Rappelez-vous, séparez tous les tests de classe/unité, etc. Chaque test doit vérifier une seule exception. Rappelez-vous, un test unitaire ne teste qu'une chose, une situation. Si votre code émet deux exceptions différentes, il ne peut pas le faire dans les mêmes conditions.

bonne chance!

+0

Merci, Cela a rendu les concepts très clairs maintenant. – dataEnthusiast