Reputation: 179
I created a previous Test method with setup for two mocked objects on a single Data Access and it worked fine. Did another one with same scenario but this turned out fail.
Here's the test method:
[Test]
public void UpdateUserPassword_WhenInputsAreCorrect_ReturnsQuerySuccessMessage()
{
UpdatePasswordModel input = new UpdatePasswordModel()
{
UserName = "john.doe",
NewPassword = "password1", //password1
PreviousPassword = "password" //password
};
Mock<IUserDataAccess> user = new Mock<IUserDataAccess>();
Mock<IDailyTimeInDataAccess> timeIn = new Mock<IDailyTimeInDataAccess>();
Mock<IDailyTimeOutDataAccess> timeOut = new Mock<IDailyTimeOutDataAccess>();
user.Setup(x => x.UpdatePassword(10000, input.NewPassword)).Returns("User record updated.");
user.Setup(x => x.GetUser(input.UserName)).Returns(new User()
{
UserKey = 10000,
UserName = "john.doe",
UserPassword = "LTg9BIob8urwz643K5+pBA=="
});
ILoginBusinessRules app = new LoginBusinessRules(user.Object, timeIn.Object, timeOut.Object);
var output = app.UpdateUserPassword(input);
Assert.AreEqual("User record updated.", output);
}
Here's the business rule:
public string UpdateUserPassword(UpdatePasswordModel model)
{
if (model == null)
{
return "No data to process.";
}
if (string.IsNullOrEmpty(model.UserName))
{
return "Username is empty.";
}
if (string.IsNullOrEmpty(model.NewPassword))
{
return "New Password is empty.";
}
if (string.IsNullOrEmpty(model.PreviousPassword))
{
return "Previous Password is empty.";
}
var user = _userDataAccess.GetUser(model.UserName);
if (user == null)
{
return "User not found.";
}
if (user.UserPassword != EncryptPassword(model.PreviousPassword))
{
return "Previous password does not match.";
}
else
{
user.UserPassword = EncryptPassword(model.NewPassword);
user.UpdateDttm = DateTime.Now;
user.UpdateUserId = model.UserName;
var result = _userDataAccess.UpdatePassword(user.UserKey, user.UserPassword);
return result;
}
}
The test returned a failure. Further debugging told me that this line here is returning null:
var result = _userDataAccess.UpdatePassword(user.UserKey, user.UserPassword);
Any help greatly appreciated!
Upvotes: 2
Views: 423
Reputation: 247098
The Setup
uses input.NewPassword
which from the test is
UpdatePasswordModel input = new UpdatePasswordModel() {
//...
NewPassword = "password1",
//...
};
//...
user.Setup(x => x.UpdatePassword(10000, input.NewPassword)).Returns("User record updated.");
//...
but in the method under test the method is called with another value
//...
user.UserPassword = EncryptPassword(model.NewPassword);
//...
var result = _userDataAccess.UpdatePassword(user.UserKey, user.UserPassword);
which wont match what was expected in the setup.
When a mocked member is not invoked with what was expected it will return the default of the return type, which in this case would be null
You would need to either make sure that the correct value is used in the setup expectation
For example
user
.Setup(x => x.UpdatePassword(10000, EncryptPassword(input.NewPassword)))
.Returns("User record updated.");
or loosen the expectation of the setup using an argument matcher like It.IsAny<T>()
user
.Setup(x => x.UpdatePassword(10000, It.IsAny<string>()))
.Returns("User record updated.");
Upvotes: 1
Reputation: 8336
To answer the question in the post, yes you can use any object that matches the input type. Your codes doesn't really know the difference between a "mock" and a "real" object.
Upvotes: 0