0

私は自分のプロジェクトにテストレイヤーを持ち込もうとしていますが、そこに到達していません:(誰かが私を助けてくれることを願っています。

コントローラ(オートマッパーマッピングと依存性注入コンテナに基づく):

    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;
    }

テストは行われましたが、機能していません:

    [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);
    }

ありがとう。

4

2 に答える 2

1

I am assuming you want to create an integration test for your category service, using real repositories and database. (as oposed to an unit test where you would use stub\mocks for those repositories and test the service class in isolation)

So you would have a seaparated test assembly where you will add your integration tests, for example having a class for the integration tests at the service level. On that class you will then create instances of all the repositories and the CategoryService before running each test, on a method with the attribute [TestInitialize]. (A method with this attribute will be run by msTest before each test)

As you are also truly working with the database you would like to be sure that any resources used are disposed. For example, disposing an entity framework context. In that case you would add a method with an attribute [TestCleanup] where you will perform any cleanup logic needed. (A method with this attribute will be run by msTest after each test)

With those methods you will make sure you have a fresh service and repositories instances on each test. Then you will implement each individual integration test following the AAA pattern (Arrange, Act, Assert)

So an example of your integration test class with that single test may look like:

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);
    }
}
于 2012-11-23T19:38:59.620 に答える
0

Autofac、Automapper(このサービスでは必要ありませんが、必要な場合は、次のソリューションのコメント行)およびDanielJGヘルプを使用したEntityFramework(Danielに感謝):

まず、MSTestを使用して個別のテストプロジェクトを作成しました(ドキュメントがたくさんあるためです)。

次に、テストデータが次の場所にあるEntityFrameworkの接続文字列を入力する必要があります。

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

</configSections>の後の<configuration>セクション

3番目に、テスト用のクラスを作成します。

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);
        }
    }

}

ここで、テストを実行して、合格するかどうかを確認する必要があります。

統合テストを保証するために、テーブルに関しては元のデータベース/本番データベースと同じであるが、テストデータのみを含む2番目のデータベースをお勧めします。

これにより、テストデータに基づいてテスト結果が同じままになります。

唯一の欠点は、テーブルを同期しておく必要があることですが、SimegoのSQLAdminStudioフリーウェアツールを使用してそれを実現できます。

よろしく。

于 2012-11-24T17:35:38.580 に答える