考虑以下单元测试:
[Test]
public void Success()
{
var userID = 5;
var user = new User();
var dataAccess = new Mock<IDataAccess>();
dataAccess.Setup(x => x.GetUser(userID)).Returns(user).Verifiable();
var sut = new UserController(dataAccess.Object);
var returnedUser = sut.GetUser(userID);
Assert.AreSame(user, returnedUser);
dataAccess.Verify(x => x.GetUser(userID), Times.Once());
}
最近的阅读建议我只应该使用mock来提供用户,并且应该有一个断言(AreSame一个)。显然,理想的单元测试不应该担心验证sut的行为。
更像这样:
[Test]
public void Success()
{
var userID = 5;
var user = new User();
var dataAccess = new Mock<IDataAccess>();
dataAccess.Setup(x => x.GetUser(userID)).Returns(user);
var sut = new UserController(dataAccess.Object);
var returnedUser = sut.GetUser(userID);
Assert.AreSame(user, returnedUser);
}
这种简化测试更好吗?单元测试应该断言他们调用的方法的行为还是结果?
答案 0 :(得分:2)
一个基本想法是在测试中只有一个Assert 。所以也许你应该考虑两个测试。第一个基于价值的测试很重要。在这种情况下,第二次交互测试可能不适合。根据Roy Osherove的说法:“在调用另一个对象时使用交互测试是特定工作单元的最终结果。”。
示例:
namespace Tests
{
[TestClass]
public class UserControllerTest
{
[TestMethod]
public void GetUser_WhenCalled_ReturnsUserSameAsDataAccess()
{
// Arrange
const int userID = 5;
User expectedUser = new User();
Mock<IDataAccess> dataAccessStub = new Mock<IDataAccess>();
dataAccessStub.Setup(x => x.GetUser(userID)).Returns(expectedUser);
UserController controller = new UserController(dataAccessStub.Object);
// Act
User actualUser = controller.GetUser(userID);
// Assert
Assert.AreSame(expectedUser, actualUser);
}
[TestMethod]
public void GetUser_WhenCalled_GetUserOnDataAccessIsCalledOnce()
{
// Arrange
const int userID = 5;
const int getUserCallsCountExpected = 1;
int getUserCallsCount = 0;
Mock<IDataAccess> dataAccessMock = new Mock<IDataAccess>();
dataAccessMock.Setup(x => x.GetUser(userID)).Callback(() => getUserCallsCount++);
UserController controller = new UserController(dataAccessMock.Object);
// Act
controller.GetUser(userID);
// Assert
Assert.AreEqual(getUserCallsCountExpected, getUserCallsCount);
}
}
}