【问题标题】:Unit testing method which only calls a single dependency method - c#/xUnit/Moq仅调用单个依赖方法的单元测试方法 - c#/xUnit/Moq
【发布时间】:2018-08-31 19:50:28
【问题描述】:

不好意思承认,但单元测试对我来说还是个新事物。我对如何正确处理事情有非常坚定的把握。但是我发现很难理解的情况是,当为一个简单地返回依赖方法调用结果的方法编写单元测试时。

我发现在您实现服务层以与 DAL 层互操作的情况下,它会出现几次。

一个简单的代码示例可能会更好地描述我的要求。

注意:下面的代码示例使用 c#、xUnit 和 Moq

public class Foo {
    Bar int;
    Baz string;
}

public interface IFooRepository {
    Foo GetByBar(bar int);
}

public interface IFooService {
    Foo GetByBar(bar int);
}

public class FooService : IFooService {
    private IFooRepository fooRepository;

    public FooService(
        IFooRepository fooRepository){
        this.fooRepository = fooRepository; 
    }

    public Foo GetByBar(bar int)
    {
        return fooRepository.GetByBar(bar);
    }
}

[Fact]
public class FooServiceTests 
{
    public class GetByBarMethod 
    {
        [Fact]
        public void ShouldReturnBar()
        {
            //arrange
            var expectedFoo = new Foo() { Bar = 1, Baz = "baz" };
            var repo = new Mock<IFooRepository>();
            repo.Setup(r => r.GetByBar(1)).Returns(expectedFoo);

            var service = new FooService(repo.Object);

            //act
            var result = service.GetByBar(1);

            //assert
            Assert.Same(result, expectedFoo);
        }
    }   
}

我知道FooService 单元测试的重点是测试方法中的逻辑,而不是依赖项的逻辑。那么在这种情况下,如果它只是测试一个模拟依赖项的返回值,是否还有必要编写一个测试?

【问题讨论】:

  • 您正在测试被测方法是否按预期运行。在这种情况下,它相当简化。不要专注于实施问题。当然,最终测试是从依赖项中获取值,目标是测试被测方法在执行时的行为是否符合预期。
  • 感谢您的反馈!正如问题结尾所提到的,我明白这一点。我只是想确认我的逻辑是正确的(即这里的测试是有意义的,尽管很简单)。
  • 是的,测试是有意义的。
  • 重要的不是您要测试哪种方法,而是您要测试什么。在这种情况下,您真正​​想要测试的是服务正在使用存储库。它作为依赖项传递给您的服务,但如何保证代码实际上调用其中的存储库?因此,您的测试名称将变为 ShouldUseRepository 或类似名称。然后,您可以检查是否调用了 repo 的 GetByBar 方法。
  • @pimbrouwers moq 有一个验证方法,您可以使用它来验证一个成员是否已被调用。

标签: c# moq xunit


【解决方案1】:

这是为了回答您的评论

你能解释一下你是如何断言方法被调用的吗?

有两种方法

首先是使Setup期望Verifiable()

repo
    .Setup(r => r.GetByBar(1))
    .Returns(expectedFoo)
    .Verifiable();

然后在调用后断言它

//...code removed for brevity

//act
var result = service.GetByBar(1);

//assert
repo.Verify(); //Verifies that all verifiable expectations have been met.

第二个是在Verify 中使用类似于Setup 的表达式

例如

//...code removed for brevity

//act
var result = service.GetByBar(1);

//assert
Assert.Same(result, expectedFoo);
repo.Verify(r => r.GetByBar(1));

参考Moq Quickstart

【讨论】:

  • Verifiable 真的有必要吗?我用过很多验证,但从不使用 Verifiable。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2016-01-04
  • 2021-10-15
  • 1970-01-01
  • 2011-01-23
  • 2016-08-14
相关资源
最近更新 更多