场景:我正在学习如何进行单元测试。目前正在使用nUnit和FakeItEasy进行mvc动作方法的测试。我有一个测试来验证如果传递一个不存在的id,该方法会抛出异常。 action方法为.Single()调用存储库包装器方法,如果找不到任何内容,则会抛出异常。这很好。
在我的测试中,我执行以下操作:
问题:我遇到了测试问题。问题是,当传递无效的id时,会在伪存储库的配置代码中抛出异常,而不是在action方法本身中抛出异常。 原因很明显。配置代码在执行操作方法之前运行,配置代码在测试数据上调用.Single()...(当然故意)不包含无效的ID。因此,它会在那时抛出一个异常,甚至从未使它成为动作方法。 我不确定的是如何解决这个问题。需要在action方法中抛出异常。我不知道如何以避免这个难题的方式配置返回值。
代码:
控制器代码
public ViewResult Details(int id)
{
var dbPart = _repository
.GetSingleRecord<Part>(x => x.PartID == id);
var viewmodel = new DetailsViewModel()
{
PartID = dbPart.PartID
};
return View(viewmodel);
}
测试代码
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
// Create a fake PartID that exists
partID_that_exists = 1;
// Create a fake PartID that doesn't exist
partID_that_doesnt_exist = -100;
}
[Test]
public void an_exception_is_thrown_if_the_part_doesnt_exist()
{
// Arrange
FakeRepository.FakePartID = partID_that_doesnt_exist;
_fakeRepository = FakeRepository.Create();
_controller = new PartController(_fakeRepository);
// Act & Assert
Assert.Throws<InvalidOperationException>(() =>
_controller.Details(partID_that_doesnt_exist));
}
假存储库代码
public class FakeRepository
{
public static int? FakePartID { get; set; }
public static IBasicRepository Create()
{
// Create fake repository
var fakeRepository = A.Fake<IBasicRepository>();
// Create fake test data
var fakeParts = new List<Part>()
{
new Part()
{
PartID = 1, PartDesc = "Fake Part 1"
},
new Part()
{
PartID = 2, PartDesc = "Fake Part 2"
}
};
// Configure fake repository to return fake data
A.CallTo(() => fakeRepository.GetAllRecords<Part>())
.Returns(fakeParts);
if (FakePartID.HasValue)
{
/* BELOW CODE IS THE PROBLEM */
A.CallTo(fakeRepository)
.Where(call => call.Method.Name == "GetSingleRecord")
.WithReturnType<Part>()
.Returns(fakeParts.Single(x => x.PartID == FakePartID));
}
// Return the newly created & configured fakeRepository
return fakeRepository;
}
}
答案 0 :(得分:1)
我明白了。我需要使用ReturnsLazily()而不是Returns()。
ReturnsLazily 延迟设置方法的返回值,直到方法实际上是调用,而不是在方法的配置代码>时设置它们em>被执行。
新的,工作代码:
A.CallTo(fakeRepository)
.Where(call => call.Method.Name == "GetSingleRecord")
.WithReturnType<Part>()
.ReturnsLazily(() => fakeParts
.Single(x => x.PartID == FakePartID));