Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 我应该在什么时候声明SUT的操作?_Unit Testing_Moq - Fatal编程技术网

Unit testing 我应该在什么时候声明SUT的操作?

Unit testing 我应该在什么时候声明SUT的操作?,unit-testing,moq,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.

考虑以下单元测试:

[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());
}
[测试]
公开募捐成功()
{
var userID=5;
var user=新用户();
var dataAccess=new Mock();
dataAccess.Setup(x=>x.GetUser(userID)).Returns(user.Verifiable();
var sut=newusercontroller(dataAccess.Object);
var returnedUser=sut.GetUser(userID);
Assert.AreName(用户,返回用户);
验证(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);
}
[测试]
公开募捐成功()
{
var userID=5;
var user=新用户();
var dataAccess=new Mock();
Setup(x=>x.GetUser(userID)).Returns(user);
var sut=newusercontroller(dataAccess.Object);
var returnedUser=sut.GetUser(userID);
Assert.AreName(用户,返回用户);
}

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

一个基本思想是在测试中只有一个断言。所以也许你应该考虑两个测试。第一个基于值的测试很重要。第二个交互测试可能不适合这种情况。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);
        }
    }
}
命名空间测试
{
[测试类]
公共类UserControllerTest
{
[测试方法]
public void GetUser\u当调用时返回susersameasdataaccess()
{
//安排
const int userID=5;
用户expectedUser=新用户();
Mock dataAccessStub=new Mock();
Setup(x=>x.GetUser(userID)).Returns(expectedUser);
UserController=newusercontroller(dataAccessStub.Object);
//表演
User actualUser=controller.GetUser(userID);
//断言
Assert.AreName(预期用户、实际用户);
}
[测试方法]
public void GetUser\u调用时\u GetUserOnDataAccessIsCalledOnce()
{
//安排
const int userID=5;
const int getUserCallsCountExpected=1;
int getUserCallsCount=0;
Mock dataAccessMock=new Mock();
dataAccessMock.Setup(x=>x.GetUser(userID)).Callback(()=>getusercallscont++);
UserController=新的UserController(dataAccessMock.Object);
//表演
controller.GetUser(userID);
//断言
AreEqual(getUserCallsCountExpected,getUserCallsCount);
}
}
}

可能重复的,这是一篇很好的背景文章:我同意第一次测试。但我总是很难理解第二次测试增加了什么价值?它不是在测试API的内部实现吗?这个测试对重构有弹性吗?只要公众行为没有改变,单元测试不应该继续通过吗?@Amol是的,我认为你是对的,第二个测试可能不适合这种情况。我编辑了答案。