需要帮助在我的MVC3项目中对服务层进行单元测试。

3

我的MVC3项目有服务层和存储库层。

我的服务层:

public class UserService : IUserService
{
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public ActionConfirmation<User> AddUser(User user)
    {
        User existUser = _userRepository.GetUserByEmail(user.Email, AccountType.Smoothie);
        ActionConfirmation<User> confirmation;

        if (existUser != null)
        {
            confirmation = new ActionConfirmation<User>()
                               {
                                    WasSuccessful = false,
                                    Message = "This Email already exists",
                                    Value = null
                               };

        }
        else
        {
            int userId = _userRepository.Save(user);
            user.Id = userId;

            confirmation = new ActionConfirmation<User>()
                               {
                                   WasSuccessful = true,
                                   Message = "",
                                   Value = user
                               };
        }

        return confirmation;


    }

}

这是我的单元测试,我不确定如何执行和断言。请帮我解决问题。如果需要其他层的代码,请告诉我。我会在这里放置它们。我认为这应该足够了。

[TestFixture]
public class UserServiceTests
{
    private UserService _userService;
    private List<User> _users;
    private Mock<IUserRepository> _mockUserRepository;

    [SetUp]
    public void SetUp()
    {
        _mockUserRepository = new Mock<IUserRepository>();
        _users = new List<User>
                     {
                        new User { Id = 1, Email = "test@hotmail.com", Password = "" },
                        new User { Id = 1, Email = "test2@hotmail.com", Password = "123456".Hash() },
                        new User { Id = 2, Email = "9422722@twitter.com", Password = "" },
                        new User { Id = 3, Email = "john.test@test.com", Password = "12345".Hash() }
                     };
    }

    [Test]
    public void AddUser_adding_a_nonexist_user_should_return_success_confirmation()
    {
        // Arrange
        _mockUserRepository.Setup(s => s.Save(It.IsAny<User>())).Callback((User user) => _users.Add(user));
        var newUser = new User { Id = 4, Email = "newuser@test.com", Password = "1234567".Hash() };

        _userService = new UserService(_mockUserRepository.Object);


        // Act


        // Assert

    }

}
3个回答

5

顺便说一句,在编写代码之前编写测试用例会更好。这将允许您设计更方便的API,并且在编写测试用例时不会受到实现细节的限制。

回到你的情况。你正在使用模拟存储库,因此你不需要调用 Save 填充存储库中的一些用户。实际上,您根本不需要填充模拟。您只需返回测试场景所需的值即可。

[Test]
public void ShouldSuccesfulltyAddNonExistingUser()
{
   // Arrrange
   int userId = 5;
   var user = new User { Email = "newuser@test.com", Password = "1234567".Hash() };
   _mockUserRepository.Setup(r => r.GetUserByEmail(user.Email, AccountType.Smoothie)).Returns(null);
   _mockUserRepository.Setup(r => r.Save(user)).Returns(userId);
   _userService = new UserService(_mockUserRepository.Object);

   // Act
   ActionConfirmation<User> confirmation = _userService.AddUser(user);

   // Assert       
   Assert.True(confirmation.WasSuccessful);
   Assert.That(confirmation.Message, Is.EqualTo(""));
   Assert.That(confirmation.Value, Is.EqualTo(user));
   Assert.That(confirmation.Value.Id, Is.EqualTo(userId));
}

请记住,在创建新用户时,不应提供用户ID。只有在用户保存到存储库后才分配ID。


非常感谢,这正是我需要的。你能详细说明一下吗?(顺便说一句,在编写代码之前编写测试会更好。)“code”指的是在服务层中的实现应该在测试之后编写吗? - qinking126
1
@feelexit 没错。你要从测试不存在的代码开始。这样你就可以集中精力在代码应该做什么上,而不是如何实现。这种方法可以让你创建一个简单易用的API。写完测试后,你需要添加所需的方法(例如UserService.AddUserIUserRepository.GetUserByEmailIUserRepository.Save)来让编译器满意。然后,你可以为测试编写最简单的愚蠢实现,以便通过测试,之后再通过重构使你的代码更加优秀。 - Sergey Berezovskiy

0
// Act
var result = _userService.AddUser(newUser);
// Assert
Assert.IsTrue( /* Insert some condition about the result */ );
Assert.IsTrue( /* Rinse, wash, repeat */ );

1
"/* 洗涤,清洗,重复 */" 如果你在清洗之后漂洗,就可能不需要重复了 ;) - justSteve

0
我会从测试确认对象开始,该对象基于用户是否已存在而返回。您还要验证的另一件事是,在用户不存在时调用_userRepository.Save

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接