单元测试在它应该失败的时候通过了
Unit test is passing when it should fail
谁能看出我在下面的例子中哪里出错了。我正在编写测试以检查 ID 是否已存在。我有一个 'UserService' 调用通用存储库 'RentalsRepository' 中的方法,为我调用数据。 *请注意代码在系统中有效,只是在我的测试中无效
回购
public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
{
private readonly RentalsDBContext _Context;
private DbSet<T> entities;
string errorMessage = string.Empty;
public RentalsRepository(RentalsDBContext _Context)
{
this._Context = _Context;
entities = _Context.Set<T>();
}
public T Get(string Id)
{
return entities.SingleOrDefault(e => e.Id == Id);
} ...
用户服务
public class UserService : IUserService {
private IRentalsRepository<UserAccount> _userRepository;
public UserService(IRentalsRepository<UserAccount> userRepository)
{
this._userRepository = userRepository;
}
public UserAccount GetUserFromId(string id)
{
UserAccount user = _userRepository.Get(id);
user.Email = Encryption.DecryptFromDatabase(user.Email);
return user;
}...
测试Class
[Fact]
public void UserService_GetByID()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring1", Username = "username1"},
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());
var service = new UserService(mockRepo.Object);
UserAccount results = service.GetUserFromId("non-existant");
Assert.Equal("idstring1", results.Id);
}
当我调试时,我可以看到方法 public UserAccount GetUserFromId(string id)
中正在使用值“"non-existant"”,但它仍然以某种方式 returns 用户
最近尝试
[Fact]
public void UserService_GetUserByUsername()
{
byte[] b = Encryption.GetSalt();
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockContext = new Mock<RentalsDBContext>();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var mockRepo = new Mock<RentalsRepository<UserAccount>>(mockContext.Object);
var testClass = new UserService(mockRepo.Object);
UserAccount results = testClass.GetUserByUsername("username2");
Assert.Equal("username1", results.Username);
}
mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());
将 return 您的模拟集中的第一条记录(“idstring1”),无论您将什么字符串传递给 Get()
。假设您将模拟的数据库上下文正确地放入存储库,则根本没有理由模拟 Get()
。
话虽如此,如果您尝试测试某个 ID 是否已存在,那是存储库的功能,而不是您的服务。您的所有服务所做的就是解密电子邮件。您正在以这种方式测试存储库和服务,这不是单元测试。
编辑
我们回到您要测试的问题。如果您想测试存储库是否检索到正确的用户帐户,您可以模拟数据库上下文并使用真实存储库 class.
[Fact]
public void UserRepository_Get()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var testClass = new RentalsRepository<userAccount>(mockContext.Object);
var results = testClass.Get("username2");
Assert.Equal("username2", results.Username);
}
如果您想测试用户服务检索用户并解密电子邮件,您可以模拟存储库(它是 Get
函数)并使用真实服务 class。
[Fact]
public void UserService_GetUserByUsername()
{
var userAccount = new UserAccount { Id = "idstring2", Username = "username2", Email = "" };
var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
mockRepo.Setup(m => m.Get("idstring2").Returns(userAccount);
var testClass = new UserService(mockRepo.Object);
var results = testClass.GetUserByUsername("idstring2");
Assert.Equal("idstring2", results.Username);
Assert.AreEqual("???", results.Email);
}
如果您想同时测试存储库和服务,当然可以,但它不会是单元测试,因为您同时测试了两件事。在那种情况下,您模拟数据库上下文并使用真实的存储库和服务 classes.
[Fact]
public void UserRepository_Get()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var repository = new RentalsRepository<userAccount>(mockContext.Object);
var service = new UserService(repository);
var results = service.GetUserByUsername("username2");
Assert.Equal("username2", results.Username);
}
谁能看出我在下面的例子中哪里出错了。我正在编写测试以检查 ID 是否已存在。我有一个 'UserService' 调用通用存储库 'RentalsRepository' 中的方法,为我调用数据。 *请注意代码在系统中有效,只是在我的测试中无效
回购
public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
{
private readonly RentalsDBContext _Context;
private DbSet<T> entities;
string errorMessage = string.Empty;
public RentalsRepository(RentalsDBContext _Context)
{
this._Context = _Context;
entities = _Context.Set<T>();
}
public T Get(string Id)
{
return entities.SingleOrDefault(e => e.Id == Id);
} ...
用户服务
public class UserService : IUserService {
private IRentalsRepository<UserAccount> _userRepository;
public UserService(IRentalsRepository<UserAccount> userRepository)
{
this._userRepository = userRepository;
}
public UserAccount GetUserFromId(string id)
{
UserAccount user = _userRepository.Get(id);
user.Email = Encryption.DecryptFromDatabase(user.Email);
return user;
}...
测试Class
[Fact]
public void UserService_GetByID()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring1", Username = "username1"},
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());
var service = new UserService(mockRepo.Object);
UserAccount results = service.GetUserFromId("non-existant");
Assert.Equal("idstring1", results.Id);
}
当我调试时,我可以看到方法 public UserAccount GetUserFromId(string id)
中正在使用值“"non-existant"”,但它仍然以某种方式 returns 用户
最近尝试
[Fact]
public void UserService_GetUserByUsername()
{
byte[] b = Encryption.GetSalt();
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockContext = new Mock<RentalsDBContext>();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var mockRepo = new Mock<RentalsRepository<UserAccount>>(mockContext.Object);
var testClass = new UserService(mockRepo.Object);
UserAccount results = testClass.GetUserByUsername("username2");
Assert.Equal("username1", results.Username);
}
mockRepo.Setup(m => m.Get(It.IsAny<string>())).Returns(mockSet.Object.FirstOrDefault());
将 return 您的模拟集中的第一条记录(“idstring1”),无论您将什么字符串传递给 Get()
。假设您将模拟的数据库上下文正确地放入存储库,则根本没有理由模拟 Get()
。
话虽如此,如果您尝试测试某个 ID 是否已存在,那是存储库的功能,而不是您的服务。您的所有服务所做的就是解密电子邮件。您正在以这种方式测试存储库和服务,这不是单元测试。
编辑
我们回到您要测试的问题。如果您想测试存储库是否检索到正确的用户帐户,您可以模拟数据库上下文并使用真实存储库 class.
[Fact]
public void UserRepository_Get()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var testClass = new RentalsRepository<userAccount>(mockContext.Object);
var results = testClass.Get("username2");
Assert.Equal("username2", results.Username);
}
如果您想测试用户服务检索用户并解密电子邮件,您可以模拟存储库(它是 Get
函数)并使用真实服务 class。
[Fact]
public void UserService_GetUserByUsername()
{
var userAccount = new UserAccount { Id = "idstring2", Username = "username2", Email = "" };
var mockRepo = new Mock<IRentalsRepository<UserAccount>>();
mockRepo.Setup(m => m.Get("idstring2").Returns(userAccount);
var testClass = new UserService(mockRepo.Object);
var results = testClass.GetUserByUsername("idstring2");
Assert.Equal("idstring2", results.Username);
Assert.AreEqual("???", results.Email);
}
如果您想同时测试存储库和服务,当然可以,但它不会是单元测试,因为您同时测试了两件事。在那种情况下,您模拟数据库上下文并使用真实的存储库和服务 classes.
[Fact]
public void UserRepository_Get()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
var mockContext = new Mock<RentalsDBContext>();
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object);
var repository = new RentalsRepository<userAccount>(mockContext.Object);
var service = new UserService(repository);
var results = service.GetUserByUsername("username2");
Assert.Equal("username2", results.Username);
}