Nunit 测试相关提交 - 按 ID
Nunit Test Dependent Commits - By ID
我有一个方法可以执行两次提交 - 这是它的简化版本:
public void methodA(objectA objA, List<objectB> objB)
{
_repoA.AddAsync(objA);
var id = _repoA.SaveChanges();
if(id > 0) {
foreach (var ob in objB)
{
ob.objAId = id;
_repoB.AddRange(ob);
}
_repoB.SaveChanges();
}
}
如何在我的单元测试中 get/set id
来查看我的列表的 objAId
是否已设置并且它实际上包含两个对象 - 现在我不能 set/get id
在第一次提交时我的测试失败了:
[Fact]
public async void test()
{
var objA = new ObjA(null);
var objB = new List<ObjB>
{
new ObjB(null, null, "Test"),
new ObjB(null, null, "Test2")
});
var result = await _sut.methodA(objA, objB);
Assert.NotNull(result);
_mockFieldRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectA>()), Times.Once);
_mockFieldOptionRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectB>()), Times.Once); //fails here
_mockFieldOptionRepository.Verify(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id))); //fails here
}
注意:我不得不猜测您的一些测试设置和被模拟的接口,所以我的回答可能不完全正确。
如果我们采用您的原始代码,似乎没有设置模拟来配置代码预期发生的事情。您只是使用 Verify 来确保某些事情确实发生了。
因此,我们需要做的第一件事是配置 mock,使隐含的 mock 成为错误,并设置期望值。
_mockFieldRepository = new Mock<IFieldRepository>(MockBehaviour.Strict);
您现在会发现您收到测试错误,因为 SaveChanges 和 AddRange 不是 Setup。这很好。所以也为他们添加设置。
_mockFieldRepository.Setup(x => x.SaveChanges();
_mockFieldRepository.Setup(x => x.AddRange(It.IsAny<MyObjectA>());
_mockFieldRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectA>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectB>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id)));
最好在设置期间使用 It.Is<>,或者对于简单参数(整数、字符串等),只需传递预期值,而不是 It.Is。
在我看来,验证不是很好,因为 It.IsAny<>() 意味着,您不关心该函数是如何被调用的,所以您应该使用 It.Is (就像第三个设置一样)以 100% 确定您希望传递给该方法的参数是您确实获得的参数。
我有一个方法可以执行两次提交 - 这是它的简化版本:
public void methodA(objectA objA, List<objectB> objB)
{
_repoA.AddAsync(objA);
var id = _repoA.SaveChanges();
if(id > 0) {
foreach (var ob in objB)
{
ob.objAId = id;
_repoB.AddRange(ob);
}
_repoB.SaveChanges();
}
}
如何在我的单元测试中 get/set id
来查看我的列表的 objAId
是否已设置并且它实际上包含两个对象 - 现在我不能 set/get id
在第一次提交时我的测试失败了:
[Fact]
public async void test()
{
var objA = new ObjA(null);
var objB = new List<ObjB>
{
new ObjB(null, null, "Test"),
new ObjB(null, null, "Test2")
});
var result = await _sut.methodA(objA, objB);
Assert.NotNull(result);
_mockFieldRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectA>()), Times.Once);
_mockFieldOptionRepository.Verify(x => x.InsertAsync(It.IsAny<MyObjectB>()), Times.Once); //fails here
_mockFieldOptionRepository.Verify(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id))); //fails here
}
注意:我不得不猜测您的一些测试设置和被模拟的接口,所以我的回答可能不完全正确。
如果我们采用您的原始代码,似乎没有设置模拟来配置代码预期发生的事情。您只是使用 Verify 来确保某些事情确实发生了。
因此,我们需要做的第一件事是配置 mock,使隐含的 mock 成为错误,并设置期望值。
_mockFieldRepository = new Mock<IFieldRepository>(MockBehaviour.Strict);
您现在会发现您收到测试错误,因为 SaveChanges 和 AddRange 不是 Setup。这很好。所以也为他们添加设置。
_mockFieldRepository.Setup(x => x.SaveChanges();
_mockFieldRepository.Setup(x => x.AddRange(It.IsAny<MyObjectA>());
_mockFieldRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectA>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.IsAny<MyObjectB>()));
_mockFieldOptionRepository.Setup(x => x.InsertAsync(It.Is<MyObjectB>(p => p.Id > 0 && p.objAId == objA.Id)));
最好在设置期间使用 It.Is<>,或者对于简单参数(整数、字符串等),只需传递预期值,而不是 It.Is。
在我看来,验证不是很好,因为 It.IsAny<>() 意味着,您不关心该函数是如何被调用的,所以您应该使用 It.Is (就像第三个设置一样)以 100% 确定您希望传递给该方法的参数是您确实获得的参数。