This is my code
public class IUserService
{
void Register(string email, string password);
}
public class UserService
{
private readonly IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public void Register(string email, string password)
{
...
var registered = senderIdRepository.Insert(email, password).Result;
SendRegistrationConfirmationEmail(email);
return registered;
}
public void SendRegistrationConfirmationEmail(string email)
{
...
}
}
public class UserServiceTest
{
private readonly ISenderIdService sut;
private readonly Mock<IUserRepository> userRepository = new Mock<IUserRepository>();
[Fact]
public void User_register_test()
{
// arrange
userRepository.Setup(x => x.Insert(It.IsAny<string>(), It.IsAny<string>()))
.Returns(Task.FromResult(true));
var email = "[email protected]";
var password = "testPass@#$d";
// act
var result = sut.Register(email, password);
// assert
Assert.Equal(1, result);
}
}
When I run test User_register_test()
, SendRegistrationConfirmationEmail()
is launched. I want to prevent that, because I don't want test email sending. Is it possible to do it without having SendRegistrationConfirmationEmail
in IUserService
?
What I would like to do is ignore whole SendRegistrationConfirmationEmail()
when launching User_register_test()
, but I dont want to have void SendRegistrationConfirmationEmail(string email)
in IUserService
interface to have it mocked. It it possible to do?
CodePudding user response:
The cleanest way to solve this is to move the mail-related methods to a separate interface and a dedicated class. On the one hand, you could mock it easily; on the other hand, it also supports the Single-Responsibility-Principle.
If you do not want to do this, there is also a hack that you can use. It will work, but it has its downsides:
- Make
SendRegistrationConfirmationEmail
virtual (and maybe protected). - In the test project, you create a derived class that overrides
SendRegistrationConfirmationEmail
and replaces the send-mail-functions. - Instead of testing
UserService
directly, you test the derived class that differs only in the implementation ofSendRegistrationConfirmationEmail
.
As you see, you also have to do some work to create the hack (maybe more than solving it in a clean way); also the probability that this hack grows and that it is used later in ways that were not intended is high. Therefore, I'd opt for the clean way and refactor SendRegistrationConfirmationEmail
into an interface of its own.