我正在尝试为我创建的rest api进行单元测试。当我分别运行测试时,它们会通过。但是当我尝试一次全部运行它们时,只有1次通过。
我知道这与我尝试在evry测试中使用相同数据有关。我通过为每个测试使用新的数据库(名称)找到了解决方案。但是我想知道这是否是正确的方法吗?因为我认为必须有一种更清洁的方法。我研究了IDisposable方法,但无法使其正常工作。
这是我将数据放入db中进行测试的方式:
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);
}
}
第二次测试。在这里(我认为),我做了另一个数据库,但这不是只留下来自先前测试的数据吗?因此,如果我要进行大量测试,会不会减慢测试过程?
[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);
}
}
}
}
还有更好的方法吗?
答案 0 :(得分:0)
您需要为每个测试提供一个新的数据库,否则,如您所见,该数据库将被重新用于每个测试,并且会影响结果。
您可以阅读the docs,其中每个测试都使用新的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 pattern来填充数据库。