2013-03-19 4 views
3

J'essaie d'écrire un test unitaire simple pour le service ServiceStack, je passe par des tests en ligne et quelques threads ici. C'est le fil principal qui a le plus de détails que j'essaie d'accomplir - Unit Test HTTPRequest Headers with ServiceStack.Tests unitaires pour les services ServiceStack

Cependant, je suis confronté à des problèmes d'injection d'objet IDbConnection dans le service. Dans la méthode web, un objet dictionnaire est rempli à l'aide de la méthode GetDictionary d'OrmLite. Mais je suis incapable de me moquer car GetDictionary est la méthode d'extension.

private Mock<IDbConnection> _dbConnectionMock; 
private Dictionary<string, string> _nameValuePairs; 

[SetUp] 
public void SetUp() 
{ 
    _dbConnectionMock = new Mock<IDbConnection>(); 

    _nameValuePairs = new Dictionary<string, string>() 
    { 
      {"name","test"}, 
      {"Updatedby", "5/23/12 7:00:15 AM"}, 
      {"Address", "212 Adam St."} 
    }; 
} 

méthode d'essai

var service = new CustomerLookupService(_dbConnectionMock.Object); 
var response = (HttpResult)service.Any(new CustomerLookup { name = "test" }); 
//assert statements 

Si la méthode GetDictionary ne peut pas être moqué, je suis même prêt à appeler la méthode Web qui frappe DB, pour ce faire, je dois créer apphost.

Répondre

3

Je pense qu'il y a quelques options à examiner.

  • Mocking/stubbing/tests unitaires méthodes d'extension here, here ou d'autres taches. Je ne pense pas qu'il existe un moyen privilégié de le faire, mais il existe des options et des frameworks/bibliothèques pour vous aider.

  • Exécution d'une base de données en mémoire telle que Sqlite pour vos tests unitaires. Voir here.

  • Vous pouvez extraire IDConnection dans un CustomerLookUpRepository et injecter votre CustomerLookUpRepository dans votre service. Ensuite, vous pouvez simplement vous moquer de votre 'Repository'.

J'ai essayé cet 'arrangement'. Jusqu'à présent, il semble fonctionner pour la plupart des cas de base. Le modèle d'accès aux données provient du Redis Web Service example. YMMV, cependant.

test (utilisant RhinoMocks)

public void SomeTest() 
    { 
     var _nameValuePairs = new Dictionary<string, string>() 
     { 
      {"name","test"}, 
      {"Updatedby", "5/23/12 7:00:15 AM"}, 
      {"Address", "212 Adam St."} 
     }; 

     var mockSqlRepository = MockRepository.GenerateMock<ISqlRepository>(); 
     mockSqlRepository.Stub(
      x => x.Exec(Arg<Func<IDbConnection, Dictionary<string, string>>>.Is.NotNull)).Return(_nameValuePairs); 

     var service = new CustomerLookupService { SqlRepository = mockSqlRepository } 
     //MORE TEST CODE... 
    } 

classe de service - en utilisant ISqlRepository à IDbConnection abstraite/cacher. ISqlRepository a une fonction qui prend une fonction en tant que paramètre. La signature de la fonction (du paramètre) prend IDbConnection comme paramètre, donc je n'ai pas besoin d'écrire plusieurs méthodes pour accéder à la base de données.

public class CustomerLookupService 
{ 
    public ISqlRepository SqlRepository { get; set; } 

    public void Any(CustomerLookup request) 
    { 
     var results = 
      SqlExec<Dictionary<string, string>>((con) => con.GetDictionary<type, type>("Select id, name from table")); 
     //MORE SERVICE CODE 
    } 

    public T SqlExec<T>(Func<IDbConnection, T> fn) 
    { 
     return SqlRepository.Exec(fn); 
    } 
} 

ISqlRepository

public interface ISqlRepository 
{ 
    T Exec<T>(Func<IDbConnection, T> fn); 
} 

SqlRepository

public class SqlRepository : ISqlRepository 
{ 
    public IDbConnectionFactory DbFactory { get; set; } 

    public T Exec<T>(Func<IDbConnection, T> fn) 
    { 
     using (var con = DbFactory.OpenDbConnection()) 
     { 
      return fn(con); 
     } 
    } 
} 
+0

Il fonctionne comme un charme. J'ai un doute, si nous avons plusieurs opérations de lecture qui récupèrent des dictionnaires dans la méthode, comment se moquer de ceux dans le test. Avons-nous besoin de mentionner les objets simulés dans le même ordre. – Sunny

+0

Cette solution n'est probablement pas la meilleure si vous testez une méthode qui effectuera de nombreuses opérations de base de données et retournera le même type. Pourrait être en mesure d'atteindre des valeurs de retour de differnt en fonction de la «commande d'appel» en utilisant Rhino Mocks - http://stackoverflow.com/questions/5609589/ordering-method-return-values-with-rhino-mock-stubs – paaschpa

+0

Merci pour le répondre.Connaissez-vous des idées alternatives pour plusieurs opérations de base de données. Le fait que j'aime cette méthode est que je n'ai pas besoin de créer des dépôts individuels en violant le principe DRY. – Sunny