什么时候应该断言SUT的动作?

时间:2014-09-03 09:04:58

标签: unit-testing moq

考虑以下单元测试:

[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);
}

这种简化测试更好吗?单元测试应该断言他们调用的方法的行为还是结果?

1 个答案:

答案 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);
        }
    }
}