как запустить несколько модульных тестов, используя одни и те же данные - PullRequest
0 голосов
/ 02 января 2019

Я пытаюсь реализовать модульные тесты для API-интерфейса rest, который я создал. Когда я запускаю тесты отдельно, они проходят. Но когда я пытаюсь запустить их все за 1 ход, только 1 проход.

Я знаю, что это как-то связано с тем, как я пытаюсь использовать те же данные в каждом тесте. Я нашел решение, используя новую базу данных (имя) для каждого теста. Но мне было интересно, если это правильный путь? Поскольку я думаю, что должен быть более чистый путь. Я посмотрел на метод IDisposable, но не смог заставить его работать.

Вот как я помещаю данные в БД для проверки:

public class GameTestShould
{
    private static GameService gameService;

    private readonly DbContextOptions<GameContext> options;
    public readonly Game testGame;
    public readonly User testUser;
    public Location testLocation;


    public GameTestShould()
    {
        //Arrange For the all tests
        options = new DbContextOptionsBuilder<GameContext>().UseInMemoryDatabase(databaseName: "GameTestDB").Options;
        //arrange
        using (var globalContext = new GameContext(options))
        {
            gameService = new GameService(globalContext);

            var testUser = new User()
            {
                Username = "tempUser",
                Password = "123456"
            };
            globalContext.Users.Add(testUser);
            var location2 = new Location()
            {
                LocName = "Standbeeld Stadhuis",
                LocLat = 51.220884,
                LocLong = 4.398995,
                LocDescription = "Standbeeld Vrijheid blijheid nabij stadhuis."
            };
            var location3 = new Location()
            {
                LocName = "Het Steen",
                LocLat = 51.222773,
                LocLong = 4.397367,
                LocDescription = "Het Steen"
            };
            var location4 = new Location()
            {
                LocName = "Pieter Paul Rubens",
                LocLat = 51.219326,
                LocLong = 4.401576,
                LocDescription = "Groenplaats, standbeeld Pieter Paul Rubens."
            };
            var location5 = new Location()
            {
                LocName = "Politiekantoor",
                LocLat = 51.230754,
                LocLong = 4.4174065,
                LocDescription = "Politiekantoor"
            };
            globalContext.Add(location2);
            globalContext.Add(location3);
            globalContext.Add(location4);
            globalContext.Add(location5);

            var suspect0 = new Suspect()
            {
                //  SuspectId = 1,
                SusName = "Miss Scarlett",
                SusWeapon = "Rope",
                SusDescription = "Ms. Vivienne Sakura Scarlet",
                SusImgUrl = "https://i.pinimg.com/originals/95/ce/3d/95ce3da06af8b1c09a4b2d4fa603b7a0.jpg",
            };
            var suspect1 = new Suspect()
            {
                SusName = "Mr. Green",
                SusWeapon = "Wooden cross",
                SusDescription = "Rev. Jonathan Green.",
                SusImgUrl = "https://pbs.twimg.com/profile_images/447953368271814657/Inf33QvJ.jpeg",
            };
            var suspect2 = new Suspect()
            {
                SusName = "Colonel Mustard",
                SusWeapon = "Gun",
                SusDescription = "Col. Michael Mustard",
                SusImgUrl = "https://static.independent.co.uk/s3fs-public/thumbnails/image/2016/07/04/08/unspecified-3.jpg?width=1368&height=912&fit=bounds&format=pjpg&auto=webp&quality=70",
            };

            var suspect3 = new Suspect()
            {
                SusName = "Dr.Orchid",
                SusWeapon = "Syringe",
                SusDescription = "A Doctor, Elegant ",
                SusImgUrl = "https://static.independent.co.uk/s3fs-public/thumbnails/image/2016/07/04/08/unspecified-4.jpg?width=1368&height=912&fit=bounds&format=pjpg&auto=webp&quality=70",
            };
            globalContext.Suspects.Add(suspect0);
            globalContext.Suspects.Add(suspect1);
            globalContext.Suspects.Add(suspect2);
            globalContext.Suspects.Add(suspect3);

            var clue0 = new Clue()
            {
                ClueName = "RansomPuzzle"
            };
            var clue1 = new Clue()
            {
                ClueName = "ARKnife"
            };
            var clue2 = new Clue()
            {
                ClueName = "ARRope"
            };
            globalContext.Clues.Add(clue0);
            globalContext.Clues.Add(clue1);
            globalContext.Clues.Add(clue2);
            globalContext.SaveChanges();
        }
    }

Это первый тест

   [Fact]
    public void Throw_AppExceptionTooManyItems_Over8ItemsAdded()
    {
        var options = new DbContextOptionsBuilder<GameContext>().UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options; 

        using (var globalContext = new GameContext(options))
        {
            gameService = new GameService(globalContext);
            //act and assert 
            Exception ex = Assert.Throws<AppException>(() => gameService.CreateGame(1, 2));
            Assert.Contains("between", ex.Message);               
        }          
     }

2-й тест. Здесь (я думаю) я делаю еще один дБ, но разве это не оставляет данные предыдущего теста? Так что, если бы мне пришлось проводить много тестов, разве это не замедлило бы процесс тестирования?

   [Fact]
    public void Throw_AppExceptionWrongUser()
    {
        var options = new DbContextOptionsBuilder<GameContext>().UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options;

        using (var globalContext = new GameContext(options))
        {
            gameService = new GameService(globalContext);
            //act and assert 
            Exception ex = Assert.Throws<AppException>(() => gameService.CreateGame(2, 3));
            Assert.Equal("User does not exist.", ex.Message);
        }            
    }
}

}

Есть ли лучшие способы сделать это?

1 Ответ

0 голосов
/ 02 января 2019

Вам нужно дать каждому тесту новую базу данных, иначе, как вы видели, БД повторно используется для каждого теста и может повлиять на результаты.

Вы можете прочитать документы , которыеиспользует новый InMemoryDatabase для каждого теста.Я даю базе данных то же имя, что и у метода теста (только для ясности).

Вы можете переместить свой код БД в закрытый метод и использовать его повторно в каждом тесте, например,

[Fact]
public void Throw_AppExceptionWrongUser()
{
    var options = new DbContextOptionsBuilder<GameContext>().UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options;

        using (var globalContext = CreateNewContext(options))
        {
            gameService = new GameService(globalContext);
            //act and assert 
            Exception ex = Assert.Throws<AppException>(() => gameService.CreateGame(2, 3));
            Assert.Equal("User does not exist.", ex.Message);
        }            
    }
}

private GameContext CreateNewContext(DbContextOptions options)
{
    var globalContext = new GameContext(options);

    var testUser = new User()
        {
            Username = "tempUser",
            Password = "123456"
        };
    globalContext.Users.Add(testUser);

    return globalContext;
}

На производительность не следует сильно влиять, если только вы не заполняете базу данных в памяти большим количеством данных (но на основе вашего примера кода, который не кажется проблемой).Один из способов выяснить это - написать тесты и измерить их: -)

Если производительность является проблемой, вам следует рассмотреть возможность заполнения базы данных только данными, необходимыми для конкретного теста.Я бы порекомендовал обратиться к шаблону Builder для заполнения базы данных, если вы хотите пойти по этому маршруту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...