如何对DoWork
方法进行单元测试?
public class SomeClass {
private readonly IClass1 class1;
private readonly Class2 class2;
// IClass1 and Class2 are injected in ctor
public string DoWork() {
// do some work
if(this.class2.Method2(() => this.class1.Method1())) {
return "done!";
}
// other work
}
}
public interface IClass1 {
void Method1();
}
public class Class2 {
public virtual bool Method2(Action action) {
// return true or false
}
}
答案 0 :(得分:1)
下面的示例使用Moq和FluentAssertions来测试SomeClass.DoWork
的测试用例,其中涉及Class2
调用成员Method2
并采取行动来调用{ {1}}
IClass1.Method1
理想情况下,[TestClass]
public class SomeClassTests {
[TestMethod]
public void DoWork_Should_Be_Done() {
//Arrange
IClass1 class1 = Mock.Of<IClass1>();
Mock<Class2> class2 = new Mock<Class2>();
class2.Setup(_ => _.Method2(It.IsAny<Action>()))
.Returns(true)
.Callback((Action passedAction) => passedAction?.Invoke());
SomeClass subject = new SomeClass(class1, class2.Object);
string expected = "done!";
//Act
var actual = subject.DoWork();
//Assert
actual.Should().Be(expected); //actual == expected
Mock.Get(class1).Verify(_ => _.Method1(), Times.Once); //was action invoked
}
}
依赖关系应在接口后面抽象
Class2
但是这超出了原始问题的范围。
以上测试模拟了依赖关系及其预期行为。可以对该测试进行各种变化,以涵盖可以完全覆盖该方法的替代方案。
答案 1 :(得分:1)
从上面的代码中,我看到注入的IClass1仅用于作为注入的class2中的参数传递。这是代码的味道!!主类SomeClass不应该对Class1一无所知。 因此,我建议以一种使Class2了解Class1的方式重构代码
public class SomeClass {
private readonly IClass2 class2;
public SomeClass(IClass2 class2)
{
this.class2 = class2;
}
// class1 and class2 are injected in ctor
public string DoWork() {
// do some work
if(this.class2.Method2()) {
return "done!";
}
// other work
return string.Empty;
}
}
public interface IClass1 {
void Method1();
}
public interface IClass2
{
bool Method2();
}
public class Class2 : IClass2
{
private IClass1 class1;
public Class2(IClass1 class1)
{
this.class1 = class1;
}
public virtual bool Method2() {
// return true or false
class1.Method1();
return true;
}
}
然后您可以轻松对其进行测试。
[Test]
public void WhenMethod2ReturnTrue_ThenDoWork_ShouldReturn_Done()
{
Mock<IClass2> class2 = new Mock<IClass2>();
SomeClass someClass = new SomeClass(class2.Object);
class2.Setup(x => x.Method2()).Returns(true);
var doWork = someClass.DoWork();
Assert.That(doWork,Is.EqualTo("done!"));
}
[Test]
public void WhenMethod2ReturnFalse_ThenDoWork_ShouldReturn_Empty()
{
Mock<IClass2> class2 = new Mock<IClass2>();
SomeClass someClass = new SomeClass(class2.Object);
class2.Setup(x => x.Method2()).Returns(false);
var doWork = someClass.DoWork();
Assert.That(doWork,Is.Empty);
}
我已将Moq库用于模拟接口