dimanche 27 janvier 2019

What are some of the rules of thumb to split a test into multiple tests?

Okay, so I have this piece of code:

public TbMtUserDTO RecoverUser(long userId, UpdateTbMtUserDTO updatedData)
{
    TbMtUser user = _usersRepository.FindUserById(userId);
    if (user == null || 
       (updatedData.IdRecSet == "Password" && String.IsNullOrEmpty(updatedData.DsUpdatedPassword)))
    {
        return null;
    }

    switch (updatedData.IdRecSet)
    {
        case "Username":
            return _mapper.Map<TbMtUserDTO>(user);
        case "Password":
            user.DsPassword = PasswordHasher.Hash(updatedData.DsUpdatedPassword);
            _usersRepository.SaveChanges();
            return _mapper.Map<TbMtUserDTO>(user);
    }
    throw new InvalidOperationException(
        String.Format(RECOVER_USER_ERROR, updatedData.IdRecSet));
}

And while I was writing the test cases for that chunk of code, when I had to write the test for one of the "Password" case, this is what I did:

    [Fact]
    public void UpdatesPasswordSuccessfully()
    {
        string oldPassword = _user.DsPassword;
        UpdateTbMtUserDTO updateTbMtUserDto = new UpdateTbMtUserDTO()
        {
            IdRecSet = "Password",
            DsUpdatedPassword = "new_password"
        };
        _usersRepositoryMock
            .Setup(x => x.FindUserById(It.IsAny<long>()))
            .Returns(_user);
        _mapperMock
            .Setup(x => x.Map<TbMtUserDTO>(It.IsAny<TbMtUser>()))
            .Returns(new TbMtUserDTO());
        TbMtUserDTO userDto = _usersService.RecoverUser(_user.CdUser, updateTbMtUserDto);
        _usersRepositoryMock.Verify(x => x.SaveChanges(), Times.Once);
        Assert.NotNull(userDto);
        Assert.True(oldPassword != _user.DsPassword);
    }

As you can see, there are three asserts at the bottom of that test. I first check if SaveChanges was called, and then I verify that the method actually returned something, hence the NotNull assertion and that it actually modifies the password (the True assertion).

But I kind of feel that's not the right way to do it. But in my head those tests are related, but I'm unsure if I should split them into three different tests. The thing is that I must arrange the same pieces together for the three cases, which to be honest, I don't think it's a good idea either.

What do you guys think? I've been implementing unit-testing for a couple of months now so what are some of your rules of thumb in scenarios like these?

Aucun commentaire:

Enregistrer un commentaire