2012-11-22 79 views
0

我试图把测试层到我的项目,但我没有收到有:(希望有人能帮助我。MSTest的控制器和服务层依赖注入(Autofac)和Automapper

控制器(基于Automapper映射和依赖注入容器):

public virtual ActionResult SearchCategories(string keywords) 
    { 
     var result = _categoryService.SearchCategories(keywords); 

     var resultViewModel = Mapper. 
      Map<IList<SearchCategoriesDto>, 
       IList<SearchCategoriesViewModel>>(result); 

     return View(resultViewModel); 
    }  

服务层:

public IList<SearchCategoriesDto> SearchCategories(String keywords) 
    { 
     // Find the keywords in the Keywords table 
     var keywordQuery = _keywordRepository.Query; 

     foreach (string keyword in splitKeywords) 
     { 
      keywordQuery = keywordQuery.Where(p => p.Name == keyword); 
     } 

     // Get the Categories from the Search 
     var keywordAdCategoryQuery = _keywordAdCategoryRepository.Query; 
     var categoryQuery = _categoryRepository.Query; 

     var query = from k in keywordQuery 
        join kac in keywordAdCategoryQuery on k.Id equals kac.Keyword_Id 
        join c in categoryQuery on kac.Category_Id equals c.Id 
        select new SearchCategoriesDto 
        { 
         Id = c.Id, 
         Name = c.Name, 
         SearchCount = keywordAdCategoryQuery 
          .Where(s => s.Category_Id == c.Id) 
          .GroupBy(p => p.Ad_Id).Count(), 
         ListController = c.ListController, 
         ListAction = c.ListAction 
        }; 

     var searchResults = query.Distinct().ToList(); 

     return searchResults; 
    } 

测试maded但不工作:

[TestMethod] 
    public void Home_SearchCategories_Test() 
    { 
     // Setup 
     var catetoryService = new CategoryService(
            _categoryRepository, 
            _keywordRepository, 
            _keywordAdCategoryRepository); 

     // Act 
     var result = catetoryService.SearchCategories("audi"); 

     // Add verifications here 
     Assert.IsTrue(result.Count > 0); 
    } 

谢谢。

+0

您是否收到错误或测试是否失败? –

+0

另外,您是否为您的服务所依赖的3个存储库提供了模拟? –

+0

@Daniel,嗨,我想测试与数据库的集成。我没有得到一个错误,我只是没有得到它所需的代码。 – Patrick

回答

0

解决方案来构建使用Autofac,Automapper(在本服务中不需要,但如果需要的话,您需要将TestInitialize方法放入TestInitialize方法中进行集成测试(在本例中为类别服务),如您在以下解决方案)和Daniel JG的实体框架帮助(感谢丹尼尔):

首先我使用MSTest创建了一个单独的测试项目(仅仅因为有很多关于它的文档)。

其次,你需要把连接字符串的实体框架,测试数据是:

<connectionStrings> 
    <add name="DB" connectionString="Data Source=.\sqlexpress;Database=DBNAME;UID=DBUSER;pwd=DBPASSWORD;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> 
</connectionStrings> 

在<配置>部分</configSections>

三后创建类为测试:

namespace Heelp.Tests 
{ 
    [TestClass] 
    public class CategoryServiceIntegrationTest 
    { 
     // Respositories dependencies 
     private IRepository<Category> _categoryRepository; 
     private IRepository<Keyword> _keywordRepository; 
     private IRepository<KeywordAdCategory> _keywordAdCategoryRepository; 

     // Service under test: Category Service 
     private CategoryService _categoryService; 

     // Context under test: HeelpDB Connection String in app.config 
     private HeelpDbContext db; 

     [TestInitialize] 
     public void InitializeBeforeRunningATest() 
     { 
      // IoC dependencies registrations 
      AutofacConfig.RegisterDependencies(); 

      // HERE YOU CAN CALL THE AUTOMAPPER CONFIGURE METHOD 
      // IN MY PROJECT I USE AutoMapperConfiguration.Configure(); 
      // IT'S LOCATED IN THE App_Start FOLDER IN THE AutoMapperConfig.cs CLASS 
      // CALLED FROM GLOBAL.ASAX Application_Start() METHOD 

      // Database context initialization 
      db = new HeelpDbContext(); 

      // Repositories initialization 
      _categoryRepository = new Repository<Category>(db); 
      _keywordRepository = new Repository<Keyword>(db); 
      _keywordAdCategoryRepository = new Repository<KeywordAdCategory>(db); 

      // Service initialization 
      _categoryService = new CategoryService(_categoryRepository, 
                _keywordRepository, 
                _keywordAdCategoryRepository); 
     } 

     [TestCleanup] 
     public void CleanDatabaseResources() 
     { 
      // Release the Entity Framework Context for other tests that will create a fresh new context. 
      // With this method, we will make sure that we have a fresh service and repositories instances on each test. 
      db.Dispose(); 
     } 

     [TestMethod] 
     public void Home_SearchCategories_Test() 
     { 
      // Arrange 
      var keywords = "audi"; 

      // Act (the _categoryService instance was created in the initialize method) 
      var result = _categoryService.SearchCategories(keywords); 

      // Assert 
      Assert.IsTrue(result.Count > 0); 
     } 
    } 

}

现在您只需运行测试以查看它是否通过。

为了保证集成测试,我建议第二个数据库与原始/生产数据库在表格方面完全相同,但仅限于测试数据。

这将确保测试结果将基于您的测试数据保持不变。

唯一的缺点是您需要保持表格的新增功能,但您可以使用Simego的SQL Admin Studio免费软件工具来实现该功能。

问候。

1

我假设您想要为您的类别服务创建一个集成测试,使用真实的存储库和数据库。 (如果选择单元测试,你可以使用stub \ mocks存储这些库并单独测试服务类)

所以你需要一个海运测试程序集,你将添加你的集成测试,例如有一个类用于服务级别的集成测试。 在该类上,您将在运行每个测试之前,在具有[TestInitialize]属性的方法上创建所有存储库和CategoryService的实例。 (具有此属性的方法将在每次测试之前由msTest运行)

由于您也在真正使用数据库,因此您希望确保使用的任何资源都处置完毕。例如,处置一个实体框架上下文。在这种情况下,您可以添加一个属性为[TestCleanup]的方法,您将在其中执行所需的清理逻辑。 (具有此属性的方法将在每次测试后由msTest运行)

使用这些方法,您将确保在每个测试中都有新的服务和存储库实例。然后,你将实现AAA模式(排列,法,断言)以下每个单独的集成测试

所以与单个测试您的集成测试类的例子可能看起来像:

public class CategoryServiceIntegrationTest 
{ 
    //dependencies of your class under test 
    private ICategoryRepository _categoryRepository; 
    private IKeywordRepository _keywordRepository; 
    private IKeywordAdCategoryRepository _keywordAdCategoryRepository; 

    //your class under test 
    private CategoryService _categoryService; 

    [TestInitialize] 
    public void InitializeBeforeRunningATest() 
    { 
     //manually create instances of the classes implementing the repositories 
     //I don´t know about how they are implemented but I guess 
     //you would need to provide the name of a connection string in the config file (in that case this should be in a config file of the test project) 
     //,the connection string itself 
     //or maybe you need to initialize an entity framework context 
     _categoryRepository = new CategoryRepository(/*whatever you need to provide*/); 
     _keywordRepository = new KeywordRepository(/*whatever you need to provide*/); 
     _keywordAdCategoryRepository = new KeywordAdCategoryRepository(/*whatever you need to provide*/); 

     //Create the class under test with all repositories dependencies   
     //as it is an integration test, they are your real objects and not mocks\stubs 
     _categoryService = new CategoryService(_categoryRepository, 
               _keywordRepository, 
               _keywordAdCategoryRepository); 
    } 

    [TestCleanup] 
    public void CleanDatabaseResources() 
    { 
     //just in case you need to do something like disposing an EF context object   
    } 

    [TestMethod] 
    public void Home_SearchCategories_Test() 
    { 
     // Arrange 
     var keywords = "audi"; 

     // Act (the _categoryService instance was created in the initialize method) 
     var result = _categoryService.SearchCategories(keywords); 

     // Assert 
     Assert.IsTrue(result.Count > 0); 
    } 
} 
+0

非常感谢您的回答,但我无法获得测试通过。我使用Autofac作为ICategoryService和CategoryService的IoC容器,并使用由接口IRepository 访问的唯一存储库。关于这一切,我不知道如何创建方法“瞎”测试的存储库。我也试图把“AutofacConfig.RegisterDependencies();”在TestInitializes方法中获得所有的构造函数,但没有成功:( – Patrick

+0

因此,你的类CategoryService依赖于像IRepository 等类似的东西,但是你应该配置automapper,以便这些接口可以解析为具体的类。在你的测试中以相同的方式创建它们,另一种选择是你说的,在你的测试课程中包含和配置Autofac,并用它来解决类别服务 –

+0

嗨,再次感谢,我终于到达那里,我会发布结果。再次感谢您的时间和帮助;) – Patrick