单元测试C#中同一类中方法的交互
本文关键字:一类 方法 交互 单元测试 | 更新日期: 2023-09-27 18:26:25
我有以下代码
public ClassToTest : IClassToTest
{
private readonly DBRepository rep;
public bool MethodA()
{
//Some logic
var result=MethodB();
//Do some logic against result;
}
public ResultType MethodB()
{
return Rep.GetResult();
}
}
如果我想单元测试MethodA,测试MethodA和MethodB之间交互的最佳实践是什么?我想测试MethodA,就像测试MethodB一样,通过模拟数据库依赖关系Rep来测试,就像方法A有以下实现一样
public bool MethodA()
{
//Some logic
var result=Rep.GetResult();
//Do some logic against result;
}
但通过检查代码和测试方法中的逻辑并不是直观的。我正在寻找一个类似于这里提到的Java的解决方案。
单元测试综合服务方法
但它不适用于C#。
还有一个问题,如果MethodB是私有的,它对单元测试策略有什么影响吗?
更新:不希望更改类的结构。比如不将MethodB设置为虚拟的,或者将MethodB从类中移出到另一个测试中
提前谢谢。
您不想测试MethodA
和MethodB
之间的交互,您想测试在给定一些上下文的情况下,MethodA
将返回预期的bool
结果。
CCD_ 5调用CCD_;但CCD_ 7将在某个时刻被调用的事实是
正如您所提到的,您可以模拟依赖关系Rep
,因此MethodB
是public
还是private
并不重要。
- 模拟并注入依赖项
- 致电
MethodA
- 根据结果断言
您想要隔离您测试的方法,也就是说,您想要在测试MethodA时模拟MethodB,反之亦然。
此外,还有一个测试类的契约(或接口)的测试范式。在这个范例中,您不会担心非公共的非虚拟方法。我倾向于尽可能多地嘲笑。
我建议你使用一个嘲讽框架(smug,rhino-mocks,moq,easymock)smug是最酷的,但它还不完整——我只向你展示下面的代码(这就是如果没有嘲讽框架的帮助,它将如何工作)。
public enum ResultType
{
Ok,
NotOk,
}
public abstract class DBRepository
{
public abstract ResultType GetResult();
}
public class ClassToTest
{
public DBRepository Rep { get; set; }
public virtual bool MethodA()
{
//Some logic
var result = MethodB();
//Do some logic against result;
return result == ResultType.Ok;
}
protected virtual ResultType MethodB()
{
return Rep.GetResult();
}
}
public class DBRepositoryMock : DBRepository
{
public ResultType FakeReturn { get; set; }
public override ResultType GetResult()
{
return FakeReturn;
}
}
public class ClassToTest_MethodA : ClassToTest
{
public ResultType MethodB_FakeReturn { get; set; }
protected override ResultType MethodB()
{
return MethodB_FakeReturn;
}
}
// tests
[TestMethod]
public void Test1()
{
ClassToTest mock = new ClassToTest_MethodA();
(mock as ClassToTest_MethodA).MethodB_FakeReturn = ResultType.Ok;
Assert.IsTrue(mock.MethodA());
}
// or using injection
[TestMethod]
public static void Test2()
{
var obj = new ClassToTest();
obj.Rep = new DBRepositoryMock { FakeReturn = ResultType.NotOk };
Assert.IsFalse(obj.MethodA());
}
[TestMethod]
public void MethodAReturnsTrueGivenSomeDataAndCondition()
{
IDBRepository mockRepo = new Mock<IDBRepository>(); //Create a mock of your repository call
ClassToTest subjectToTest = new ClassToTest(mockRepo.Object); //Inject the dependency
mockRepo.SetUp(r=>r.GetResult()).Returns(someSampleTestData); //You're setting up the object that might return you true to return when mock repo will be called, by default it returns the default or null usually
var result = subjectToTest.MethodA();
mockRepo.Verify(r=>r.GetResult(), Times.Once); //Make sure your repo method was called
Assert.IsTrue(result);
}
类似这样的东西,使用Moq作为一个示例嘲讽框架。