gpt4 book ai didi

c# - 我的单元测试是否关心太多

转载 作者:太空狗 更新时间:2023-10-29 20:31:18 24 4
gpt4 key购买 nike

我对我的单元测试方法有 2 个顾虑:

  1. 我是否在一种测试方法中测试了太多?
  2. 我的测试方法名称如何反射(reflect)所有测试预期?

当我的方法名称说:ReturnInvalidModelState 时,我问自己,然后我的其他 2 个 Asserts 不正确。至少关于方法名...

[Test]
public void Create_TemplateAlreadyExists_ReturnInvalidModelState()
{
// ARRANGE
TemplateViewModel templateViewModel = new TemplateViewModel {
Name = "MyTest"
};

Mock<ITemplateDataProvider> mock1 = new Mock<ITemplateDataProvider>();
Mock<IMappingEngine> mock2 = new Mock<IMappingEngine>();

TemplateController controller =
new TemplateController(mock1.Object, mock2.Object);
mock1.Setup(m => m.TemplateExists("MyTest")).Returns(true);
// Set ModelState.IsValid to false
controller.ModelState.AddModelError("Name",
"This name already exists.");

// ACT
ActionResult result = controller.Create(templateViewModel);

// ASSERT
Assert.IsFalse(controller.ModelState.IsValid);
Assert.IsInstanceOfType(typeof(PartialViewResult), result);
Assert.AreEqual(templateViewModel, ((PartialViewResult)result).Model);
}

[HttpPost]
public ActionResult Create(TemplateViewModel templateViewModel)
{
if (ModelState.IsValid
&& !_templateDataProvider.TemplateExists(templateViewModel.Name))
{

Template template =
Mapper.Map<TemplateViewModel, Template>(templateViewModel);

_templateDataProvider.AddTemplate(template);
return new JsonNetResult(new { success = true });
}
ModelState.AddModelError("Name", "This name already exists.");
return PartialView(templateViewModel);
}

最佳答案

是的,我认为您正在测试太多东西。

从重命名您的测试方法开始。您的方法签名应描述操作、场景和预期结果。

如果我要重命名您的方法,那么我最终会得到以下内容:

public void Create_DuplicateTemplate_ModelStateIsInvalidAndReturnsPartialViewResultAndPartialViewResultOfTypeTemplateViewModel() 
{
}

您的测试关注三件事,而不是一件。当它失败时,您不会立即知道它失败的原因。

考虑将其重构为更小的测试并封装一些排列逻辑,以便可以重复使用。

编辑:

您在关于具有单一断言的单一测试方法的评论中提出了一个很好的观点。我同意你的观点,尽管听起来不错,但通常是不够的。

假设我有以下操作方法:

[HttpPost]
public ActionResult Register(NewUserViewModel newUser)
{
if (!ModelState.IsValid)
return View(newUser);

var newUserDTO = Mapper.Map<NewUserViewModel, NewUserDTO>(newUser);
var userDTO = UserManagementService.RegisterUser(newUserDTO);

var result = Mapper.Map<UserDTO, UserViewModel>(userDTO);

TempData.Add("RegisteredUser", result);
return RedirectToAction("RegisterSuccess");
}

我对此方法进行了以下单元测试:

        [TestMethod]
public void Register_HttpPost_ValidViewModel_ReturnsRegisterSuccess()
{
// Arrange
var autoMapperMock = this.mockRepository.DynamicMock<IMapper>();
var userManagementServiceMock = this.mockRepository.DynamicMock<IUserManagementService>();

var invalidRegistrationViewModel = new NewUserViewModel
{
LastName = "Lastname",
FirstName = "Firstname",
Username = null
};

autoMapperMock.Expect(a => a.Map<UserDTO, UserViewModel>(Arg<UserDTO>.Is.Anything)).Repeat.Once().Return(null);
autoMapperMock.Expect(a => a.Map<NewUserViewModel, NewUserDTO>(Arg<NewUserViewModel>.Is.Anything)).Repeat.Once().Return(null);
userManagementServiceMock.Expect(s => s.RegisterUser(Arg<NewUserDTO>.Is.Anything)).Repeat.Once();

autoMapperMock.Replay();

var controller = new AccountController
{
Mapper = autoMapperMock,
UserManagementService = userManagementServiceMock
};

this.mockRepository.ReplayAll();

// Act
var result = (RedirectToRouteResult)controller.Register(invalidRegistrationViewModel);

// Assert
Assert.IsTrue((string)result.RouteValues["Action"] == "RegisterSuccess");
}

如您所见,我在模拟中设置了多个期望值:

  • 我希望 AutoMapper 被调用两次
  • 我希望 UserManagementService 被调用一次

在测试结束时,我有一个断言来检查用户是否被重定向到正确的路径。

那么我在哪里检查我的断言?我创建了另一种方法来确保满足我的期望:

    [TestCleanup]
public void Cleanup()
{
try
{
this.mockRepository.VerifyAll();
}
finally
{
}
}

所以你是对的,我有三个断言而不是一个,但我以这样一种方式构建我的代码,所以看起来我只有一个断言。

关于c# - 我的单元测试是否关心太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12277390/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com